素數之篩法
阿新 • • 發佈:2018-11-08
篩法
篩素數的常用手段:
1、Eratosthenes 篩法
複雜度:O(n log (log n))
從小到大找到一個素數,篩掉所有它的倍數。
程式碼:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 void Prim(int n) 2 { 3 //Eratosthenes篩選法 4 memset(check,false,sizeof(check)); 5 int tot = 0; 6 for(int i = 2;i <= n;i ++) 7 if(!check[i]) 8 { 9 prim[tot++] = i;View Code10 for(int j = 2*i;j <= n;j += i) 11 check[j] = true; 12 } 13 }
2、Euler 篩法(重要!!!)
複雜度:O(n)
鑑於前者演算法的優化,因為上面的演算法一個非素數可能會被多個質因數篩多次,浪費了,所以優化掉這個,只用一個數最小的質因數排除(篩掉)這個數字。
1 void Euler_prim(int n) 2 { 3 //尤拉篩選法 避免上面篩選法中的重複篩選4 memset(check,false,sizeof(check)); 5 int tot = 0; 6 for(int i = 2;i <= n;i ++) 7 { 8 if(!check[i]) prim[tot ++] = i; 9 for(int j = 0;j < tot;j ++) //遍歷已經找到的素數 10 { 11 if(i * prim[j] > n) break; //後面相乘已經超出 n 的範圍,沒有查詢的必要了 12 check[i * prim[j]] = true; //表示這個數字不是素數 13 if(i % prim[j] == 0) break; 14 } 15 } 16 }
重點解釋下 if (i%prim[j]==0) break 這句話:
因為prim[j]是i的最小質因數了,如果這時候繼續篩下去,下一個數為i*prim[j+1],因為 i=prim[j]*k,對於這個數來說最小質因數是prim[j],而這時卻要用prim[j+1]來篩,則與我們要達到的要求、效果違背,這個數肯定會在以後被Prim[j]篩掉,所以直接break就行了,後面的肯定也會被prim[j]篩掉。
(不知道這樣理解對不對。。。)
fighting fighting fighting !!!