欧拉函数的定义:1到N中与N互质的数的个数被称为欧拉函数,记做F(N)。
若N=p1^c1*p2^c2*.........*pm^cm。(pi为质数)
那F(N)=N*(p1-1)/p1*(p2-1)/p2*.......*(pm-1)/pm
证明:设p是N的质因子,1到N中p的倍数有p,2*p,3*p,......(N/p)*p,一共N/p个。同理,
如果q也是N的质因子,那1到N中q的倍数也有N/q个。如果把N/p+N/q个数去掉,那
根据容斥原理可知,p*q的倍数被排除了两次,需要加回来一次,所以1到N中不与N
含有共同质因子p或q的数的个数为:
N-(N/p)-(N/q)+N/(p*q)=N*(1-1/p-1/q+1/(p*q))=N*(1-1/p)*(1-1/q);
根据欧拉函数的计算式,我们只需要分解质因数便可求出欧拉函数。
int phi(int n) { int ans=n; for(int i=2;i<=sqrt(n);i++) { if(n%i==0)//i是素数 { ans=ans/i*(i-1); while(n%i==0) n/=i; } } if(n>1) ans=ans/n*(n-1); return ans; }
关于欧拉函数的一些性质:
对于所有的n>1,1到n中与n互质的数的和为n*F(n)/2;
如果a,b互质,则F(a*b)=F(a)*F(b);
设p为质数,如果n%p==0&&n%(p*p)==0,那么F(n)=F(n/p)*p;
设p为质数,如果n%p==0&&n%(p*p)!=0,那么F(n)=F(n/p)*(p-1);
求2到n中每个数的欧拉函数:
可以利用素筛并按照欧拉函数的计算式,可以在O(N*logN)的时间内求出2到n中每个数的欧拉函数。
void euler(int n) { for(int i=2;i<=n;i++) phi[i]=i; for(int i=2;i<=n;i++) { if(phi[i]==i) { for(int j=i;j<=n;j+=i) phi[j]=phi[j]/i*(i-1); } } }
利用线性筛和欧拉函数的一些性质可以在O(N)的时间复杂度内求出2到n里的欧拉函数。
int v[maxn],prime[maxn],phi[maxn]; void euler(int n) { 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; } //给当前的数i乘上一个质因子 for(int j=1;j<=m;j++) { if(prime[j]>v[i]||prime[j]>n/i) break; //prime[j]是合数i*prime[j]的最小质因子 v[i*prime[j]]=prime[j]; if(i%prime[j]) phi[i*prime[j]]=phi[i]*(prime[j]-1); else phi[i*prime[j]]=phi[i]*prime[j]; } } }