1.埃氏篩法:時間復雜度是O(nlognlogn),打表把一定范圍內的質數都記錄在數組里所以空間復雜度較高。具體的實現是通過兩個數組一個prime記錄當前范圍的質數序號,另一個isprime判斷是否是素數,將isprime初始化為1,從i=2開始遍歷標記所有i的倍數的數的isprime為零。
代碼:
1 #include<iostream> 2 #include<algorithm> 3 #include<vector> 4 #include<cstring> 5 #include<cstdio> 6 using namespace std; 7 #define mem(s,n) memset(s,n,sizeof s); 8 typedef long long ll; 9 const int maxn=9e2+1; 10 const int Inf=0x7f7f7f7f; 11 bool isPrime[maxn]; 12 int primes[maxn]; 13 //當然,當數據太大導致普通數組存不下的時候,可以采用stl里的vector來存 14 int cnt; 15 void judgePri() 16 { 17 mem(isPrime, 1); 18 cnt = 0; 19 isPrime[1] = 0;//1特殊處理 20 for (int i = 2; i < maxn; i++) 21 { 22 if (isPrime[i] == 1) 23 { 24 primes[cnt++] = i; 25 for (int j = i; j < maxn; j += i) //標記i在N范圍內的所有倍數 26 { 27 isPrime[j] = 0; 28 } 29 } 30 } 31 } 32 33 int main(void) 34 { 35 judgePri(); 36 for (int i = 0; i < cnt; i++) 37 { 38 if(i%9==0) cout<<endl; 39 printf("%d ", primes[i]); 40 } 41 return 0; 42 }
然而我們會發現一個問題就是有重復標記的情況,舉個例子6第一次i=2時就已經標記了但是i=3又遍歷了一次,這樣其實就是浪費操作了,所以引入一種改進算法歐拉算法。
2.歐拉算法:時間復雜度O(n),主體思路還是建立在埃氏篩法的基礎上,對其重復標記進行了優化。我們很容易想到只用合數中的一個因數篩選掉這個合數。思路實現——利用前面求得的質數,從小到大遍歷如果i被prime[j]整除那么跳出循環,同時也把i*prime[j]遍歷了標記成合數。(具體實現見代碼)
代碼
#include<iostream> #include<algorithm> #include<vector> #include<cstring> #include<cstdio> using namespace std; #define mem(s,n) memset(s,n,sizeof s); typedef long long ll; const int maxn=9e2+1; const int Inf=0x7f7f7f7f; bool isPrime[maxn]; int primes[maxn]; int cnt; void judgePri() { int temp; mem(isPrime, 1); cnt = 0; isPrime[1] = 0; for (int i = 2; i < maxn; i++) { if (isPrime[i] == 1) primes[cnt++] = i; //優化 for (int j = 0; j < cnt && (temp = i * primes[j]) < maxn; j++) //找i之前的所有質數 { isPrime[temp] = 0;//i * primes[j]肯定是合數,先標記掉 if (i % primes[j] == 0)//關鍵,每次整除一個最小的質數將會跳出循環,所以每個數字,只會被最小的質數篩一次 { break; } } //優化 } } int main(void) { judgePri(); for (int i = 0; i < cnt; i++) { if(i%9==0) cout<<endl; printf("%d ", primes[i]); } return 0; }
3.常用板子:
1 int f[maxn];//f[i]表示i的因子個數 2 int pri[maxn]; 3 int notpri[maxn]; 4 int prime[maxn]; 5 ll p[maxn]; // p[i] 表示 i由幾個素因子組成如 p[6]=2 2*3 p[8]=3 2*2*2 6 void init(){ 7 now=0;f[1]=1; 8 notpri[0]=notpri[1]=1; 9 for(int i=2;i<=maxn-1;i++){ 10 if(!notpri[i])pri[++now]=i,f[i]=2,p[i]=1; 11 for(int j=1;j<=now&&pri[j]*i<=maxn-1;j++){ 12 notpri[i*pri[j]]=1; 13 if(i%pri[j]==0){//有pri[j]作為質因子時 14 f[i*pri[j]]=f[i]*(p[i]+2)/(p[i]+1); 15 p[i*pri[j]]=p[i]+1ll; 16 break; 17 } 18 f[i*pri[j]]=f[i]*f[pri[j]];//互質則直接乘 19 p[i*pri[j]]=p[i]+1ll; 20 } 21 } 22 // rep(i,1,10) { 23 // cout<<i<<" "<<p[i]<<endl; 24 // } 25 rep(i,1,maxn-1) pre[i]=pre[i-1]+p[i]; 26 }
