素數的埃式篩選法的思想:對於不超過n的每個正整數,刪除2的倍數,3的倍數,4的倍數……n-1的倍數,當處理完所有數之後,還沒有被刪除的就是素數。
void getprime(int n) //從0到n篩選素數
}vis[0]=vis[1]=1;
}
這裡介紹乙個唯一分解定理:任何乙個大於1的自然數 n,如果n不為素數,那麼n可以唯一分解成有限個素數的乘積。
優化:由唯一分解定理可知合數一定是素數的倍數,所以就不用再對它們的倍數進行處理而重複操作了。
所以我們可以在第6行和第7行之間插入:
if(!vis[i])
對乙個 i(i>2),i 的2~ i-1倍數之前已經處理,所以只需處理 i 的 i~∞ 的倍數的情況。如果i>sqrt(n),則i*i>n,那麼處理的倍數就是沒有意義的。故第4行可改為:
for(int i=2;i<=sqrt(n);i++)
想想可不可以再優化?
我們可以打打草稿看一下:
2的倍數:4 6 8 10 12 14 16 18 20……
3的倍數:6 9 12 15 18 ……
5的倍數:10 15 20……
可以發現其中還是有重複操作的情況,3的2倍,5的2倍都是2的倍數,5的三倍都是3的倍數,這些數在處理2的倍數,3的倍數時已經處理過,而我們只需考慮3的3倍,3的4倍……5的5倍,5的6倍……
因此我們可以把第7行**改為:
for(int j=i*i;j<=n;j+=i)
再加乙個陣列prime存放素數
這樣可以得到乙個比較好的演算法
int prime[n1]; //存放素數的陣列
bool vis[n1]; //判斷是否為素數
void getprime(int n) //從0到n篩選素數}}
vis[0]=vis[1]=1;
}
還可不可以再優化?
是的,可以。
尤拉篩選可以做到o(n)的時間複雜度,因為給出的演算法已經可以應付大多數的素數題目,這裡就不再討論了。這裡給出乙個**,有興趣的朋友可以研究一下
其實還有一種厲(wu)害(lai)的方法:
事先寫乙個程式對一億以內的素數打表,輸出素數文字,然後把它們放在解題**的陣列裡,到時直接查表,即使你不會什麼演算法,也可以這樣做。
WV 51 素數篩選優化
合數過濾篩選法 演算法描述 我們知道,素數 n不能被 2 n 1 間的任何數整除 反過來看,只要能被 2 n 1 間的任何數整除的 n,都不是素數。所以我們可以採用乙個簡單的排除法 就是對 n以內的所有數,只要逐個去除值為 2 n 1 的倍數的數,剩下的就是素數。c 語言實現 合數過濾篩選法 ver...
質數篩選 素數篩選法
int prime 100010 void prime for int i 1 i i 1000000 i define size 1000000 int main 元素值為0代表是素數 int prime size int pos 0 int flag for int i 2 i size i p...
素數篩選法
篩選素數法 搞acm的都知道,素數是數論中必不可少的知識,也是必須要掌握的,關於素數的篩選有好幾種方法,下面一一道來,寫的不好還請提出。第一種是最常規的做法 int main if j sqrt i cout 這種方法肯定是比第一種快的,至於快多少大家可以比較一下,注意到裡面的for迴圈是到sqrt...