欧拉函数
定义
欧拉函数 φ ( x ) \varphi(x) φ(x),表示1~x所有数中与x互质的数的个数。
计算公式
欧拉函数有两个神奇的规律:
1.如果x为素数,则 φ ( x ) = x − 1 \varphi(x)=x-1 φ(x)=x−1
2.如果 g c d ( x , y ) = 1 gcd(x,y)=1 gcd(x,y)=1,则 φ ( x ∗ y ) = φ ( x ) ∗ φ ( y ) \varphi(x*y)=\varphi(x)*\varphi(y) φ(x∗y)=φ(x)∗φ(y)
证明见Orz zzkksunboy,我的智商已经无法承受这个证明了,自己看。
那么现在要得到欧拉函数的通项公式
对n分解质因数,有 n = p 1 x 1 ∗ p 2 x 2 ∗ … ∗ p k x k n=p_1^{x_1}*p_2^{x_2}*…*p_k^{x_k} n=p1x1∗p2x2∗…∗pkxk
注意,这k个数都互质,所以 φ ( n ) = φ ( p 1 x 1 ) ∗ φ ( p 2 x 2 ) ∗ … ∗ φ ( p k x k ) \varphi(n)=\varphi(p_1^{x_1})*\varphi(p_2^{x_2})*…*\varphi(p_k^{x_k}) φ(n)=φ(p1x1)∗φ(p2x2)∗…∗φ(pkxk)
所以问题又变成了求 φ ( p k ) \varphi(p^k) φ(pk)
而显而易见的是,因为p是素数,所以在1~ p x p^x px中除了p的倍数外所有数都与 p x p^x px互质。而有多少个数呢? p k p \frac{p^k}{p} ppk个。
所以 φ ( p k ) = p k − p k k = p k ∗ ( 1 − 1 p ) \varphi(p^k)=p^k-\frac{p^k}{k}=p^k*(1-\frac{1}{p}) φ(pk)=pk−kpk=pk∗(1−p1)
所以综上,欧拉函数的通项公式为 φ ( n ) = n ∗ ( 1 − 1 p 1 ) ∗ ( 1 − 1 p 2 ) ∗ … … ∗ ( 1 − 1 p k ) \varphi(n)=n*(1-\frac {1}{p_1})*(1-\frac {1}{p_2})*……*(1-\frac {1}{p_k}) φ(n)=n∗(1−p11)∗(1−p21)∗……∗(1−pk1)
求法
对于要求的欧拉函数的次数大致有两种方法。
1.唯一分解法
专门求 φ ( x ) \varphi(x) φ(x),直接找出所有x的素数。然后通项公式解决。
int getp(int x){
int sum=x; for (int i=2,S=sqrt(x);i<=S;i++) if (x%i==0) {sum=sum/i*(i-1); while (x%i==0) x/=i;}
if (x>1) sum=sum/x*(x-1); return sum;
}
2.筛法,如果要求多次欧拉函数,那么可以筛法求出 φ \varphi φ(1~n)然后O(1)得到。
这里采用本身效率高的欧拉筛用来求欧拉函数。
void makep(){
memset(vs,1,sizeof(vs)); vs[0]=vs[1]=0; p[0]=0; phi[1]=1;
for (int i=2;i<=maxn;i++){
if (vs[i]) {p[++p[0]]=i; phi[i]=i-1;}
for (int j=1;j<=p[0]&&i*p[j]<=maxn;j++){
vs[i*p[j]]=0;
if (i%p[j]) phi[p[j]*i]=phi[p[j]]*phi[i];
else {phi[p[j]*i]=p[j]*phi[i]; break;}
}
}
}
扩展
同样copy于zzk
1~n与n互质的所有数的和为:
n=1:nφ(n)/2+1/2=1
n>1:nφ(n)/2
其实很好求:如果(x,n)=1,那么(n-x,n)=1。也就是说与n互质的数是成对出现的,那么显然这些数的和为n*φ(n)/2(1比较特殊,需要特判)。
欧拉定理
如果 g c d ( a , p ) = 1 gcd(a,p)=1 gcd(a,p)=1,有 a φ ( p ) ≡ 1 ( m o d p ) a^{\varphi(p)}\equiv1(mod\ p) aφ(p)≡1(mod p)
注意费马小定理:当p为素数时,存在 a p − 1 ≡ 1 ( m o d p ) a^{p-1}\equiv1(mod\ p) ap−1≡1(mod p) 而此时 φ ( p ) = p − 1 \varphi(p)=p-1 φ(p)=p−1,所以一个有趣的发现:费马小定理其实是欧拉定理的特殊情况