一、线性筛求欧拉函数值--->复杂度O(n)
可以在筛出质数的同时求出每个数的欧拉函数值,主要公式有两条:
1.当i%prime[j]==0时:
phi[i*prime[j]]=i*prime[j]*(1-1/p1)*....*(1-1/prime[j])*...
由分解质因数易知phi[i]=i*(1-1/p1)*.....*(1-1/prime[j])*...
所以phi[i*prime[j]]=phi[i]*prime[j]。
2.当i%prime[j]!=0时:
因为prime[j]是质数,所以很明显i与prime[j]互质,那么因为欧拉函数是积性函数,所以:
phi[i*prime[j]]=phi[i]*phi[prime[j]]=phi[i]*(prime[j]-1)。
代码:
1 #include<cstdio> 2 const int N=1e5+5; 3 int prime[N],phi[N],cnt=0; 4 int n=100000; 5 bool vis[N]; 6 void make_phi(){ 7 vis[0]=vis[1]=1; 8 for(int i=2;i<=n;i++){ 9 if(!vis[i]){ 10 prime[++cnt]=i; 11 phi[i]=i-1; 12 } 13 for(int j=1;j<=cnt&&prime[j]*i<=n;j++){ 14 vis[i*prime[j]]=1; 15 if(i%prime[j]==0){ 16 phi[i*prime[j]]=phi[i]*prime[j]; 17 break; 18 } 19 else phi[i*prime[j]]=phi[i]*(prime[j]-1); 20 } 21 } 22 } 23 int main(){ 24 make_phi(); 25 for(int i=2;i<=10;i++) 26 printf("%d %d\n",i,phi[i]); 27 return 0; 28 }
二、求单个数的欧拉函数值--->复杂度O(sqrt(n))
代码:
1 #include<cstdio> 2 #include<cmath> 3 int n; 4 int get_phi(int x){ 5 int res=x; 6 for(int i=2;i<=sqrt(x);i++){ 7 if(!(x%i)){ 8 res/=i;res*=i-1; 9 while(!(x%i))x/=i; 10 } 11 } 12 if(x^1)res/=x,res*=x-1; 13 return res; 14 } 15 int main(){ 16 scanf("%d",&n); 17 printf("%d",get_phi(n)); 18 return 0; 19 }