wenbao與篩法素數及判斷模板
阿新 • • 發佈:2018-04-14
phi void flag htm html display euler 發現 經典
1 #define ll long long 2 const int maxn = 1000000; 3 int vis[maxn],prime[maxn]; 4 void isprime() 5 { 6 memset(vis,0,sizeof(vis)); 7 ll cot=0,i,j; 8 for( i=2;i<=1000000;i++) 9 { 10 if(!vis[i]) 11 { 12 prime[cot++]=i; 13 for( j=i*i;j<1000000;j+=i) 14 vis[j]=1; 15 } 16 } 17 }
判斷模板
1 bool prime(int x) 2 { 3 if(x==2) 4 return true; 5 if(x%2==0||x==1) 6 return false; 7 bool flag=true; 8 int t=(int )sqrt((double)x); 9 for(int i=3; i<=t; i+=2) 10 if(x%i==0) 11 { 12 flag=false; 13 break; 14 } 15 return flag; 16 }
http://blog.csdn.net/lerenceray/article/details/12420725
1 #include<cstring> 2 #include<iostream> 3 #include<ctime> 4 using namespace std; 5 #defineN 100000005 6 7 bool vis[N]; 8 int p[N], cnt, phi[N]; 9 10 int Euler(int n){ 11 int i, j, k; 12 phi[1] = 1; 13 for (i = 2; i < n; ++i){ 14 if (!vis[i]){ 15 p[cnt++] = i; 16 phi[i] = i - 1; 17 } 18 for (j = 0; j < cnt && i * p[j] < n; ++j){ 19 vis[i * p[j]] = true; 20 if (i % p[j]) phi[i * p[j]] = phi[i] * phi[p[j]]; 21 else { 22 phi[i * p[j]] = phi[i] * p[j]; 23 break; 24 } 25 } 26 } 27 return cnt; 28 } 29 30 int Eratosthenes (int n){ 31 int i, j, k; 32 phi[1] = 1; 33 for (i = 2; i < n; ++i){ 34 if (!vis[i]) p[cnt++] = i; 35 for (j = i; j < n; j += i) { 36 if (!phi[j]) phi[j] = j; 37 phi[j] = phi[j] / i * (i - 1); 38 vis[j] = true; 39 } 40 } 41 return cnt; 42 } 43 44 int main(){ 45 clock_t st, en; 46 int num; 47 double sec; 48 for (int t = 10; t < N; t *= 10){ 49 cout << t << ‘:‘ << endl; 50 st = clock(); 51 num = Euler(t); 52 en = clock(); 53 sec = (double)(en - st) / (double) CLOCKS_PER_SEC; 54 //cout << "Euler : " << cnt << ‘ ‘ << sec << endl; 55 printf("Euler :\t\t%8d\t%.8lf\n", num, sec); 56 memset(vis, 0, sizeof(vis)), memset(p, 0, sizeof(p)), memset(phi, 0, sizeof(phi)), cnt = 0; 57 st = clock(); 58 num = Eratosthenes(t); 59 en = clock(); 60 sec = (double)(en - st) / (double) CLOCKS_PER_SEC; 61 //cout << "Eratosthenes : " << cnt << ‘ ‘ << sec << endl; 62 printf("Eratosthenes :\t%8d\t%.8lf\n", num, sec); 63 } 64 return 0; 65 }
http://www.bubuko.com/infodetail-837565.html
我們先來看一下最經典的埃拉特斯特尼篩法。時間復雜度為O(n loglog n)
1 int ans[MAXN]; 2 void Prime(int n) 3 { 4 int cnt=0; 5 memset(prime,1,sizeof(prime)); 6 prime[0]=prime[1]=0; 7 for(int i=2;i<n;i++) 8 { 9 if(vis[i]) 10 { 11 ans[cnt++]=i;//保存素數 12 for(int j=i*i;j<n;j+=i)//i*i開始進行了稍微的優化 13 prime[j]=0;//不是素數 14 } 15 } 16 return ; 17 }
顯然,當一個數是素數的時候,那麽他的倍數肯定是合數,篩選標記即可。從i*i而不從i*2開始,是因為已經i*3,i*2早已經被2,3篩過了。
由此,我們也可以發現有的合數被重復篩除,例如30,2*15篩了一次,5*6重復篩除,所以也就有了我們下面要提到的歐拉線性篩法。
不會重復篩除,是線性O(n)的復雜度。
1 const int MAXN=3000001; 2 int prime[MAXN];//保存素數 3 bool vis[MAXN];//初始化 4 void Prime(int n) 5 { 6 int cnt=0; 7 memset(vis,0,sizeof(vis)); 8 for(int i=2;i<n;i++) 9 { 10 if(!vis[i]) 11 prime[cnt++]=i; 12 for(int j=0;j<cnt&&i*prime[j]<n;j++) 13 { 14 vis[i*prime[j]]=1; 15 if(i%prime[j]==0)//關鍵 16 break; 17 } 18 } 19 return cnt;//返回小於n的素數的個數 20 }
1 void prime(){ 2 a[0] = a[1] = 1; 3 for(int i = 2; i < maxn; i++){ 4 if(!a[i]){ 5 b[num] = i, num++; 6 } 7 for(int j = 0; j < num && i*b[j] < maxn; j++){ 8 a[i*b[j]] = 1; 9 if(i%b[j] == 0) break; 10 } 11 } 12 }
只有不斷學習才能進步!
wenbao與篩法素數及判斷模板