求質數3 線性篩法 C實現

2021-06-28 08:35:39 字數 1809 閱讀 7389

該問題出自《c語言名題精選百則技巧篇》

從2開始,先刪除2*2, 2*2*2,2*2*2*2,...接著刪除2*3, 2*2*3 ,2*2*2*3,...(3並沒有被刪除),再刪除2*5, 2*2*5, 2*2*2*5,...;然後刪除2*7, 2*2*7, 2*2*2*7,...;然後是2*9, 2*2*9, 2*2*2*9,...。當發現p是乙個質數的時候,先刪除p*p, p*p*p, p*p*p*p,,,,。因為p是個質數,p*p, p*p*p, p*p*p*p,,,,不可能被其他整數整除,所以在此之前不可能被整除,接著去找比p大的,但沒被刪除的數,因此,q*(p*p*p*...*p)(i個p)在此之前也沒有被刪除過。

如果找出2~n的所有質數,p*p<=n。刪除的工作可以寫成:

for(p=2;p*p<=n;next(p))

for(q=p;p*q<=n;next(q))

for(m=p*q;m<=n;m=p*m)

remove(m)

next(p)用來找比p大但還未被刪除的下乙個數,它一定是質數,如果它不是質數,在比p小的數進行搜尋的時候,就已經把它給刪除了;找到p以後,令q從p起,刪除pq, p*p*q, p*p*p*q,....之後再去找出下乙個沒有被刪除的數做q,如此迴圈。

用乙個雙向連線序列(double linked list),在開始的時候第i個元素的previous[i]是i-1,next(i)是i+1,previous(2)沒有上乙個,next(n)沒有下乙個,用null表示。用乙個函式來初始化這兩個陣列。

比如n=20。

previous =

next        =  

要刪除某乙個數,例如m,也很簡單,只要m的上乙個元素(previous[m])的下乙個指標(next[previous[m]]))指向m的下乙個元素(next[m]),再將m的下乙個元素的上乙個指標(previous[next[m]])指向m的上乙個元素(previous[m])就可以了,這個叫做remove(m).

比如要刪除4,6,8,10,12,14,16,18,20這些元素,previous和next變成

previous =

next        =  

再刪除9和15

previous =

next        =  

從next裡取出質數,從2開始i=2,輸出2,下乙個i=next[i] = 3,輸出3;下乙個i = next[3] = 5,輸出5;下乙個i=next[5] = 7,輸出7;下乙個i=next[7] = 11, 輸出11;下乙個i = next[11] = 13,輸出13;下乙個i=next[13] = 17,輸出17;下乙個i=next[17] = 19,輸出19;下乙個i=next[19] = null,結束。

程式如下:

#include #include #define maxsize 400

#define next(x) x=next[x]

#define remove(x)

#define initial(n)

int main(int argc,char *argv)

printf("\n\nthere are %ld prime numbers in total",count);

getchar();

return 0;

}

執行結果

質數線性篩法 O n

埃氏篩法o nloglogn 仍會重複標記合數 such as i 2時 12 2 6,先會被 2 標記已是合數 i 3時 12 3 4,又被標記了一次 我們在生成乙個需要標記的合數時,每次只向現有的數中乘上乙個質因子,並且讓它是所生成合數的最小質因子 code include include us...

線性篩質數,線性求尤拉

本篇前半部分講線性篩質數,也叫尤拉篩,後半篇講解線性求尤拉函式。我們有一種篩質數的辦法,就是列舉每個質數,然後把這個質數的倍數都篩掉,這個做法比較簡單,在這裡不做過多介紹。尤拉篩就是在這個方法的基礎上,使得每個合數只會被它最小的那個質因子篩掉,保證了複雜度是線性的 memset isprime,1,...

篩法求素數 線性篩法求素數

2021年更新版 篩法求素數 線性篩法求素數 要理解篩法求素數首先要知道乙個定理,整數唯一分解定理 任意大於等於2的正整數都有且只有一種方式寫出其質因子的乘積表示式。a p1p2p3p4 pn pi是素數且pi pj eg 2 2 4 22 12 223 36 2233 也就是說任意乙個合數都能分成...