欧拉函数 φ(n) 定义:[1,N]中与N互质的数的个数
//互质与欧拉函数 /* 求欧拉函数 按欧拉函数计算公式,只要分解质因数即可 */ int phi(int n){ int ans=n; for(int i=2;i<=sqrt(n);i++){ if(n%i==0){ ans=ans/i*(i-1); while(n%i==0) n/=i; } } if(n>1) ans=ans/n*(n-1); return ans; }
性质:1.[1,n]中与n互质的数的和为 n*φ(n)/2;
2.欧拉函数是积性函数
3.p|n && p*p|n =>φ(n)=φ(n/p)*p;
4.p|n && p*p不能整除n,则φ(n)=φ(n/p)*(p-1);
5.sum{φ(d)}=n,d是n的约数
打表求欧拉函数
第一种是era筛的思路,O(nlogn)的复杂度,即每个质数p的倍数都乘以(1-1/p)即可
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int phi[10000]; void euler(int n){//用era筛的思路O(nlogn)复杂度 for(int i=2;i<=n;i++)phi[i]=i; for(int i=2;i<=n;i++) if(phi[i]==i)//i是质数 for(int j=1;i*j<=n;j++) phi[i*j]=phi[i*j]/i*(i-1); } int main(){ int t,n; euler(1000); scanf("%d",&t); for(int tt=1;tt<=t;tt++){ scanf("%d",&n); int ans=0; for(int i=2;i<=n;i++) ans+=2*phi[i]; printf("%d %d %d ",tt,n,ans+3); } }
第二种是线性筛的思路:复杂度O(n)
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int phi[10000]; int m,v[10000],prime[10000]; void euler(int n){//用era筛的思路O(nlogn)复杂度 memset(v,0,sizeof v); m=0; for(int i=2;i<=n;i++){ if(v[i]==0){//i是质数 v[i]=i,prime[++m]=i; phi[i]=i-1; } for(int j=1;j<=m;j++){ if(prime[j]>v[i] || prime[j]*i>n) break; v[i*prime[j]]=prime[j]; phi[i*prime[j]]=phi[i]*(i%prime[j]?prime[j]-1://φ(n)=φ(n/p)*(p-1) 性质4 prime[j]);//φ(n)=φ(n/p)*p 性质3 } } } int main(){ int t,n; euler(1000); scanf("%d",&t); for(int tt=1;tt<=t;tt++){ scanf("%d",&n); int ans=0; for(int i=2;i<=n;i++) ans+=2*phi[i]; printf("%d %d %d ",tt,n,ans+3); } }