线性筛的思想:每个被筛的数是通过它最小的质因子所筛去的。
这种思想保证了每个数只会被筛一次,从而达到线性。并且,这个思想实现起来非常巧妙(见代码注释)!
因为线性筛的操作中用到了倍数的关系去实现,因此欧拉函数可以顺便也计算出来,根据完全积性函数的性质还有数学推算,直接一条语句就算出来了。
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 }