快速查找素數
時間限制:
1000 ms | 內存限制:65535 KB
難度:
3
- 描述
- 現在給你一個正整數N,要你快速的找出在2.....N這些數里面所有的素數。
- 輸入
-
給出一個正整數數N(N<=2000000)
但N為0時結束程序。
測試數據不超過100組 - 輸出
- 將2~N范圍內所有的素數輸出。兩個數之間用空格隔開
- 樣例輸入
-
5 10 11 0 - 樣例輸出
- 2 3 5
- 2 3 5 7
- 2 3 5 7 11
- 【分析】
- 枚舉法:
1 //根據概念判斷: 2 //如果一個正整數只有兩個因子, 1和p,則稱p為素數. 3 //代碼: 4 bool isPrime(int n) 5 { 6 if(n < 2) return false; 7 8 for(int i = 2; i < n; ++i) 9 if(n%i == 0) return false; 10 return true; 11 } 12 //時間復雜度O(n)
1 //改進, 去掉偶數的判斷 2 //代碼: 3 bool isPrime(int n) 4 { 5 if(n < 2) return false; 6 if(n == 2) return true; 7 if(n % 2 == 0) return false; 8 for(int i = 3; i < n; i += 2) 9 if(n%i == 0) return false; 10 return true; 11 } 12 //時間復雜度O(n/2), 速度提高一倍.
1 /進一步減少判斷的范圍 2 //定理: 如果n不是素數, 則n有滿足1<d<=sqrt(n)的一個因子d. 3 //證明: 如果n不是素數, 則由定義n有一個因子d滿足1<d<n. 4 //如果d大於sqrt(n), 則n/d是滿足1<n/d<=sqrt(n)的一個因子. 5 //代碼: 6 bool isPrime(int n) 7 { 8 if(n < 2) return false; 9 if(n == 2) return true; 10 if(n % 2 == 0) return false; 11 for(int i = 3; i*i <= n; i += 2) 12 if(n%i == 0) return false; 13 return true; 14 } 15 //時間復雜度O(sqrt(n)/2), 速度提高O((n-sqrt(n))/2).
- 篩選法
- 顯然以上的枚舉法,不管如何改進都是不能AC的,所以枚舉法肯定是行不通的。
- 用篩法求素數的基本思想是:把從1開始的、某一范圍內的正整數從小到大順序排列, 1不是素數,首先把它篩掉。剩下的數中選擇最小的數是素數,然后去掉它的倍數。依次類推,直到篩子為空時結束。如有:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
- 1不是素數,去掉。剩下的數中2最小,是素數,去掉2的倍數,余下的數是:
- 3 5 7 9 11 13 15 17 19 21 23 25 27 29
- 剩下的數中3最小,是素數,去掉3的倍數,如此下去直到所有的數都被篩完,求出的素數為:
- 2 3 5 7 11 13 17 19 23 29
1 //篩法判斷素數 一 2 #include<cstdio> 3 #define MAXN 2000001 4 int a[MAXN],i,j; 5 int main(){ 6 int m; 7 //篩選出二百萬內的所有素數 8 for(i = 2;i <= 2000000;i++){ 9 if(a[i]==0) 10 //利用數組的下標,將i的倍數全部篩掉 11 for(j = i + i;j <= 2000000;j += i) 12 a[j] = 1; 13 } 14 while(scanf("%d",&m) && m!=0){ 15 //從數組中依據下標取出[2,m]內的所有素數 16 for(i = 2;i <= m;i++){ 17 if(a[i] == 0){ 18 printf("%d ",i); 19 } 20 } 21 printf("\n"); 22 } 23 return 0; 24 }
1 //篩法判斷素數 二 2 #include<cstdio> 3 #define MAXN 2000001 4 int a[MAXN],i,j; 5 int main(){ 6 int m; 7 while(scanf("%d",&m) == 1 && m!=0){ 8 //m有多大,數組用多大 9 for(i = 2;i <= m;i++) 10 a[i] =i; 11 //m/2縮小范圍 12 for(i = 2;i <= m/2;i++){ 13 if(a[i] != 0){ 14 for(j=i+i;j <= m;j += i){ 15 //將i的倍數全部篩掉 16 a[j] = 0; 17 } 18 } 19 } 20 for(i = 2;i <= m;i++){ 21 if(a[i] != 0) printf("%d\n",a[i]); 22 } 23 // printf("\n"); 24 } 25 return 0; 26 }
- 素數打表法
正在研究..... 先挖個坑。
順便吐槽NYOJ的服務器。還能再爛么?
