链接:http://www.cnblogs.com/yefeng1627/archive/2013/01/02/2842492.html
欧拉函数直接计算公式
欧拉函数的定义: E(N)= ( 区间[1,N-1] 中与 N 互质的整数个数).
对于 积性函数 F(X*Y),当且仅当 GCD(X,Y)= 1 时, F(X*Y) = F(X)* F(Y)
任意整数可因式分解为如下形式:
其中( p1, p2 ... pk 为质数, ei 为次数 )
所以
因为 欧拉函数 E(X)为积性函数, 所以
对于 , 我们知道 因为pi 为质数,所以 [ 1, pi-1 ] 区间的数都与 pi 互质
对于 区间[ 1, ] ,共有 个数, 因为 只有一个质因子,
所以与 约数大于1 的必定包含 质因子 , 其数量为
所以
又 E(N)为积性函数,所以可得 :
又因为 其中( p1, p2 ... pk 为质数, ei 为次数 )
但是此计算公式,除法过多,所以计算速度较慢
在程序中利用欧拉函数如下性质,可以快速求出欧拉函数的值 ( P为N的质因子 )
若(N%P==0 && (N/P)%P==0) 则有:E(N)=E(N/P)*P;
若(N%P==0 && (N/P)%P!=0) 则有:E(N)=E(N/P)*(P-1);
求单个数的欧拉函数:
long long eular(long long n) { int i; long long ans=n; for(i=2;i*i<=n;i++) { if(n%i==0) { ans-=ans/i; while(n%i==0) n/=i; } } if(n>1)ans-=ans/n; return ans; }
筛法欧拉函数:
int eular[MAXN+1]; void getEular() { int i,j; memset(eular,0,sizeof(eular)); eular[1]=1; for(i=2;i<=MAXN;i++) { if(!eular[i]) for(j=i;j<=MAXN;j+=i) { if(!eular[j]) eular[j]=j; eular[j]=eular[j]/i*(i-1); } } }
线性筛(同时得到欧拉函数和素数表)
bool check[MAXN+10]; int phi[MAXN+10]; int prime[MAXN+10]; int tot; void phi_and_prime_table(int N) { int i,j; memset(check,false,sizeof(check)); phi[1]=1; tot=0; for(i=2;i<=N;i++) { if(!check[i]) { prime[tot++]=i; phi[i]=i-1; } for(j=0;j<tot;j++) { if(i*prime[j]>N)break; check[i*prime[j]]=true; if(i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j]; break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1); } } }