1. 程式人生 > >wenbao與篩法素數及判斷模板

wenbao與篩法素數及判斷模板

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 #define
N 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與篩法素數及判斷模板