歐拉篩(求質數)
阿新 • • 發佈:2018-05-05
sta tar locks ide running nbsp 圖片 sizeof rim
先上代碼:
#include<stdio.h> #include<iostream> #include<string.h> #include<time.h> using namespace std; int prime[10000001];//存素數 bool vis[10000001];//保證不做素數的倍數 int main() { int n, cnt = 0; scanf("%d", &n); clock_t start = clock(); memset(vis, false, sizeof(vis));//初始化 memset(prime, 0View Code, sizeof(prime)); for(int i = 2; i <= n; i++) { if(!vis[i]) { prime[cnt++] = i; for(int j=1;j*i<=n;j++) { vis[j*i]=true; } } } clock_t ends = clock(); cout <<"Running Time : "<<(double)(ends - start)/ CLOCKS_PER_SEC << endl; printf("%d\n", cnt); return 0; }
這並不是完整的歐拉篩,上面的代碼從2開始把素數的倍數全部標記為非質數,計算一千萬以內的質數個數只需要0.23s
完整歐拉篩代碼:
#include<stdio.h> #include<string.h> #include<time.h> #include<iostream> using namespace std; int prime[10000001]; boolView Codevis[10000001]; int main() { int n, cnt = 0; scanf("%d", &n); clock_t start = clock(); memset(vis, false, sizeof(vis)); memset(prime, 0, sizeof(prime)); for(int i = 2; i <= n; i++) { if(!vis[i]) prime[cnt++] = i; for(int j = 0; j<cnt && i*prime[j]<=n; j++) { vis[i*prime[j]] = true; if(i % prime[j] == 0) break; } } clock_t ends = clock(); cout <<"Running Time : "<<(double)(ends - start)/ CLOCKS_PER_SEC << endl; printf("%d\n", cnt); return 0; }
計算一千萬以內的質數個數只需要0.12s
先講講為什麽可以這樣算質數吧
首先,先將所有的數標記為質數,然後從2開始,因為2是質數所以它的倍數肯定不是質數,然後3同理,4已經被標記為非質數了跳過,5質數,6也被標記為非質數了跳過.....
然後講一講為什麽第一個會比第二個快
為什麽會這樣了?
首先,第一個代碼標記2的倍數是標記過1次6,而標記3的倍數時有標記了一次6,所以重復標記花費了時間
而第二個代碼,因為這句代碼而沒有進行重復標記:
for(int j = 0; j<cnt && i*prime[j]<=n; j++)
{
vis[i*prime[j]] = true;
if(i % prime[j] == 0) break;//重點
}
當 i % prime[j] == 0,相當於i=k*prime[j],所以i*preime[i+1]=k*prime[j]*preime[i+1],是質數的倍數,而後面會對他進行標記,所以這次就跳過,終止循環.
第一個代碼也可以這樣寫:
#include<stdio.h> #include<iostream> #include<string.h> #include<time.h> using namespace std; int prime[10000001];//存素數 bool vis[10000001];//保證不做素數的倍數 int main() { int n, cnt = 0; scanf("%d", &n); clock_t start = clock(); memset(vis, false, sizeof(vis));//初始化 memset(prime, 0, sizeof(prime)); for(int i = 2; i <= n; i++) { if(!vis[i]) { prime[cnt++] = i; } for(int j = 0; j<cnt && i*prime[j]<=n; j++) { vis[i*prime[j]] = true; } } clock_t ends = clock(); cout <<"Running Time : "<<(double)(ends - start)/ CLOCKS_PER_SEC << endl; printf("%d\n", cnt); return 0; }View Code
歐拉篩(求質數)