素數的篩選方法 從暴力篩選到線性篩選

2021-09-27 08:01:46 字數 1112 閱讀 4780

也被就叫做試除法,對於每乙個整數n,你都可以進行一次從2到根號n的篩選,如果這個數不能被從2到根號n的任意乙個數整除,就可以確定這個數是素數.

int prime[maxn],num;

void ******_screening(int n)

}if(!flag) prime[num++]=i;

}}

對於這種最樸素的方法所需的時間複雜度也是最高的,對於每乙個n你需要o(n2)的時間複雜度。

樸素的篩選方法在競賽中肯定是行不通的。那麼我們這樣考慮乙個問題:對於每個質數,他的任意不包括一的整數倍必然是乙個合數。我們可以對從2到n的整數這樣篩選:每當找到乙個質數時,便幫他的任意倍標記為合數。如果這個數被標記為合數,那便跳過對這個數的操作。

int prime[maxn],num,visit[maxn];

void eratosthenes(int n)

prime[num++]=i;}}

}

那麼,這種方法的時間複雜度是在2到n中所有的質數的n/p的加和。化簡後也就是o(n log log n),這個複雜度接近線性,比賽時大多數時候使用這種方法。

埃氏篩是非常接近線性的篩法,但是當遇到n=10000000的情況時還是會被卡掉。我們對埃氏篩分析會發現,這個數i有多少個質因子就會被篩掉多少次,對此我們可以這樣處理

int prime[maxn],num,visit[maxn];

void euler(int n)

{ for(int i=2;i<=n;i++){

if(!visit[i]) prime[num++]=i;

for(int j=0;j注意這裡面的這個if語句

if(!(i%prime[j])) break;

這個語句就表明的每個合數只被他的最小質因子標記一次。

沒有這個語句,會繼續標記i * prime[j+1],但是i裡有個質因子是prime[j],也就意味這這個被標記的數同時也會被prime[j] * (i/prime[j]*prime[j+1])標記一次。這樣就會發成同乙個合數被標記多次的情況。也就是說這個if語句使得同乙個合數被標記且只被標記一次。當然這個演算法的時間複雜度是o(n)。

素數線性篩選

include include includeusing namespace std bool isprime 10000001 int pri 2000001 prin int findprime int maxn for int j 0 jmaxn break 當過大了就跳出 isprime i...

線性篩選素數

侵刪。題目 給出乙個正整數n,列印出所有從1 n的素數 即質數 關鍵是要找出乙個判斷乙個正整數n是否為素數的方法 傻瓜解法 n,n 2 1 include2 int main 3 12 這裡迴圈取到sqrt n 效率改進不少了 但顯然還是不夠理想 繼續往下看 普通篩選法 埃拉託斯特尼篩法 先簡單說一...

素數的線性篩選

出處 線性篩選法之所以稱之為線性就是因為其對於每乙個合數只用其最小的素因子將其篩選出來。如下 include include include define maxn 1000000 using namespace std int p 1000005 pri 1000005 idx 1 void ge...