關於線性篩法
線性是指O(n)內篩掉所有合數,還有一種方法叫埃氏篩法,我先證明埃氏篩法效率低,也就是會有重復。
證明如下:
埃氏篩法的原理是找到一個素數后,它的1~n倍就會被篩掉,任何一個合數都可以被拆成一個質數*另一個數的形式,我們對每一個質數對應的可能的(合)數都枚舉了,這就保證了所有可能的合數都被篩掉了。為什么不是最優呢?問題出在那個質數上,對於一個合數m,m=h*P,P是質數且P>m的最小質因數,那么m也可以表示為m=H*p,(H是個比h大的合數,p是m的最小質因數),這樣我們在枚舉p的倍數時,m就被篩掉了,而在枚舉P的倍數時,m又被篩掉了一次,造成效率浪費。
怎辦呢?--------線性篩法
我們在枚舉倍數時,保證當前質數不能整除這個倍數就好了,當然了,在之前要先篩一次,也就是p是m的p,這樣我們在最優性的條件下,對每一個質數,它所有對應的倍數,都被枚舉到,也就保證了可行性。
代碼如下:
#include<bits/stdc++.h> using namespace std; int n,cnt; int prime[100000]; bool vis[100000]; void Euler(){ for(int i=2;i<=n;i++){ if(!vis[i]) prime[++cnt]=i; for(int j=1;j<=cnt&&i*prime[j]<=n;j++){ vis[i*prime[j]]=1; if(i%prime[j]==0) break; } } } int main(){ cin>>n; Euler(); for(int i=1;i<=cnt;i++) cout<<prime[i]<<' '; return 0; }
里面關鍵就是那個break,如果不break,就是再往大里枚舉,那么以后枚舉到的質數,一定不是最小質數,因為它都比當前質數大了,怎么可能最小,最小也只可能是當前的質數,從而實現了優化。