PTA 基礎181 關於素數篩法的思考

2021-10-03 00:21:19 字數 3858 閱讀 4244

pta 181 求因子和

c++格式化輸出

微秒級計時

素數篩演算法

因子和公式

直接使用sqrt(n)為迴圈上限的方法,時間穩定o(sqrt(n)),程式執行不會超時

素數篩法理論複雜度小於o(sqrt(n)),在因子遠小於n的情況下能達到最佳效果

由於演算法相對複雜,素數篩法的執行時間會更高

在大數區間[108,109]內隨機選取的平均運算時間是 素數篩: 開方法 ≈2: 1部分執行結果可見下圖,前4個數為比較有代表性的測試數字,最後為4中的平均時間

//開方法

intsumoffactor_sqrt

(int n )

return n % i? sum: sum+i;

}

然而素數篩法會在篩素數的過程消耗大量時間,在不優化的情況下其複雜度和開方法一樣都是o(sqrt(n)),優化思路落在了迴圈上限上。由於不需要求得每個因子的值,可以在求出每乙個素因子後讓n除去改素因子,通過降低n的值降低迴圈的次數。因此,根據上一段中關於最後乙個素數的判斷方法,設n的最大素因子為p,次數為q,則素數篩法理論時間複雜度為o( max( log(n), sqrt(pq) ) )

int

sumoffactor_sieve

(int n )

sum *

= v;

}for

(int j =

0; j < pcnt && i*primes[j]

<= n/i/primes[j]

; j++

) isnotprime[i*primes[j]]=

true;}

if( n >

1) sum *

=( n+1)

; sum -

= num;

return sum;

}

#include

#include

#include

#include

#include

#include

using

namespace std;

int primes[

100000];

int pcnt =0;

bool isnotprime[

100000]=

;void

decompose

(int n )

if(flag && c)

cout <<

" + ";if

(c)}

for(

int j =

0; j < pcnt && i*primes[j]

<= n/i/primes[j]

; j++

) isnotprime[i*primes[j]]=

true;}

if( n >1)

cout <<

" + "

<< n <<

"^"<<1;

cout << endl;

}int

sumoffactor_sieve

(int n )

sum *

= v;

}for

(int j =

0; j < pcnt && i*primes[j]

<= n/i/primes[j]

; j++

) isnotprime[i*primes[j]]=

true;}

if( n >

1) sum *

=( n+1)

; sum -

= num;

return sum;

}int

sumoffactor_sqrt

(int n )

intsumoffactor_sub2

(int n )

intmain()

; testlen =

sizeof

(testvalue)

/sizeof

(int);

cout <<

"一共 "

<< testlen <<

" 組測試資料"

<< endl;

cout << endl;

for(

int i =

0; i < testlen; i++)

rtime = rtime2 =0;

int rmax =

1000000000

;int rmin =

100000000

;int times =

10000

;for

(int i =

0; i < times; i++

) rtime /

= times;

rtime2 /

= times;

cout <<

"====平均用時==== "

; cout <<

"max = "

<< scientific <<

setprecision(2

)<<

(double

)rmax <<

", "

; cout <<

"min = "

<< scientific <<

setprecision(2

)<<

(double

)rmin <<

", "

; cout <<

"rounds = "

<< times;

cout << endl;

cout <<

setw(16

)<< left <<

"素數篩法"

<<

"用時 : "

; cout <<

setw(2

)<< rtime /

1000000

<<

"s "

; cout <<

setw(4

)<<

(rtime /

1000)%

1000

<<

"ms "

; cout <<

setw(4

)<< rtime %

1000

<<

"us"

<< endl;

cout <<

setw(16

)<< left <<

"開方法"

<<

"用時 : "

; cout <<

setw(2

)<< rtime2 /

1000000

<<

"s "

; cout <<

setw(4

)<<

(rtime2 /

1000)%

1000

<<

"ms "

; cout <<

setw(4

)<< rtime2 %

1000

<<

"us"

<< endl;

return0;

}

素數的篩法

素數的篩法有很多種 在此給出常見的三種方法 以下給出的所有 均已通過這裡的測試 名字好長 joy 不過 很短 思路非常簡單,對於每乙個素數,列舉它的倍數,它的倍數一定不是素數 這樣一定可以保證每個素數都會被篩出來 還有,我們第一層迴圈列舉到 sqrt n 就好,因為如果當前列舉的數大於n,那麼它能篩...

改進的篩素數法

最簡單的篩素數法方法就是從2開始,將所以2的倍數去掉,然後從3開始,將3的倍數去掉。根據這樣很容易寫出 下面 就是是篩素數法得到100以內的素數並儲存到primes陣列中。cpp view plain copy by morewindows const intmaxn 100 bool flag m...

改進的篩素數法

最簡單的篩素數法方法就是從2開始,將所以2的倍數去掉,然後從3開始,將3的倍數去掉。根據這樣很容易寫出 下面 就是是篩素數法得到100以內的素數並儲存到primes陣列中。const int maxn 100 bool flag maxn int primes maxn 3 pi void getp...