線性篩的思想:每個被篩的數是通過它最小的質因子所篩去的。
這種思想保證了每個數只會被篩一次,從而達到線性。並且,這個思想實現起來非常巧妙(見代碼註釋)!
因爲線性篩的操作中用到了倍數的關係去實現,因此歐拉函數可以順便也計算出來,根據完全積性函數的性質還有數學推算,直接一條語句就算出來了。
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<math.h> 5 #include<algorithm> 6 #include<queue> 7 #include<stack> 8 #include<deque> 9 #include<iostream> 10 using namespace std; 11 typedef long long LL; 12 const int N = 100009; 13 14 int check[N]; 15 int prime[N]; 16 int phi[N]; 17 int cnt; 18 19 20 void is_prime(int n) 21 { 22 int i,p,j; 23 cnt=0; 24 phi[1]=1; 25 for(i=2;i<=n;i++) 26 { 27 if(!check[i]) 28 { 29 prime[cnt++]=i; 30 phi[i]=i-1; 31 } 32 for(j=0;j<cnt;j++) 33 { 34 if(i*prime[j]>n) 35 break; 36 check[i*prime[j]]=1; 37 38 if(i%prime[j]==0) 39 { 40 /*因爲 i%prime[j]==0 ,所以i 是 prime[j] 的倍數, i 就可以看成 prime[j]*k , 這樣 41 就相當於篩去 prime[i]的k*prime[j+1] 倍,但是這個數不應當現在被處理,而是在 i==prime[j+1]*k時被篩掉 */ 42 43 phi[i*prime[j]]=phi[i]*prime[j]; // 因爲prime[j] 是質數,所以prime[j] 不可再分解,因此 i*prime[j] 的分解形式爲 i 的分解形式再乘以 prime[j], 44 // 根據 歐拉函數的定義,i*prime[j] 的歐拉函數爲 prime[j]*phi[i] ; 45 break; 46 } 47 else 48 phi[i*prime[j]]=phi[i]*(prime[j]-1); //當 i 不是 prime[j] 的倍數的時候,歐拉函數位完全積性函數,滿足積性函數的特點 49 } 50 } 51 } 52 int main() 53 { 54 int i,p,j,n; 55 is_prime(100); 56 for(i=0;i<cnt;i++) 57 { 58 printf("%d ",prime[i]); 59 } 60 return 0; 61 }