演算法筆記 素數篩(樸素篩,埃式篩,尤拉篩)

2021-10-10 03:12:06 字數 1457 閱讀 5898

素數也叫質數,是指在大於1的自然數中,除了1和它本身以外不再有其他因數的自然數。如2 , 3 , 5 , 7 , 11等。

素數篩即篩選出1~n內的素數的方法,這裡介紹三種

由上面的概念得,我們可以想到引入乙個從1到它本身的for迴圈,只要中間有取余為0,那麼它就不是素數。

#define max 100000

int prime[max]

;int x=0;

void

psshai

(int n)}if

(flag==0)

//標記未解除,說明該數是素數

prime[

++x]

=i;//儲存

}}

這種演算法就是暴力列舉,優化後時間複雜度o(n*sqrt(n))。不推薦,太慢。

我們知道最小的素數是2,埃氏篩就是從2開始,在判斷該數是否為素數的同時將該數的倍數篩去,因為乙個數(從2開始)的倍數一定不是素數,注意一下範圍別超過n就行

#define max 100000

bool isprime[max]

;void

asshai

(int n)}}

}

這種演算法的時間複雜度是o(nlogn),但是我們會發現裡面的一些操作有點冗餘。比如數字6,它既是2的3倍又是3的2倍,這樣在篩選的時候被篩出去兩次,其實是在重複的做無用功。即使這樣,這種演算法一般的題也能用

尤拉篩就是對埃氏篩的優化了,即使乙個數僅被一次篩除

#define max 100000

bool vis[max]

;//預設都是false

1、當 i 是素數時,儲存素數,並剔除 i 的整數倍,其中整數應為素數且小於等於前 i 個數中已知最大的素數,注意乘積小於等於n

2、當 i 不為素數,剔除 i 的整數倍,在注意上面(其中整數應為素數且小於等於前 i 個數中已知最大的素數,注意乘積小於等於n)要求的同時判斷 i % prime[j],如果整除則退出

i % prime[j]這一步就是對埃氏篩的優化,舉個例子理解一下

如果沒有這一步,那麼當i=9時,prime=2,prime=3,prime=5,prime=7;本來是當 j=2 的時候跳出迴圈,但是卻沒有,那麼j = 3時 9 * 5 =45,該統計在 i = 15 的時候也會統計,也就是當 i = 15 時候,j = 2 ,prime = 3,也統計了 3 * 15 = 45 ,明顯,重複統計,所以要及時break。

尤拉篩的時間複雜度是o(n),所以普遍使用尤拉篩來篩選素數

有所借鑑。

埃式篩與尤拉篩

核心思想 每個質數的倍數都是合數,當發現乙個質數時就將其的倍數都變成合數。缺點 有的合數會被它的幾個質因子重複篩掉,造成了時間上的浪費。include include using namespace std int n,q,cnt,k bool isprime 100000005 int sushu...

素數篩法 埃氏篩及尤拉篩

在做題中會經常遇到有關素數的問題,整理一下學過的兩種素數篩法。時間複雜度 o nloglogn 我們知道乙個素數的倍數肯定是乙個合數,乙個合數可以由多個素數相乘得到,所以可以從2開始把2的倍數篩一遍,找到下個素數在篩一遍。篩完後素數的倍數都被篩掉了,剩下的就是素數。如下 const int n 1e...

埃式篩法和尤拉篩判斷素數

一般要判斷是是否為素數,我們通常找出了1和它本身之外是否存在可以被它整除的數。接著對判斷可以進行優化,出去偶數,判斷的邊界設定為math.sqrt number 如 以輸入101 200之間的素數為例 public static void fun1 else flag true if flag 還有...