参考书籍:《ACM-ICPC程序设计系列--数论及应用》
欧拉函数φ(n)指不超过n且与n互质的正整数的个数,其中n是一个正整数。
欧拉函数的性质:它在整数n上的值等于对n进行素因子分解后,所有的素数上的欧拉函数之积。
定义:
1.定义在所有正整数上的函数称为算数函数
2.算法函数f如果满足对任意两个互质的正整数n和m,均有f(mn)=f(n)f(m),就称为积性函数。如果对任意的两个正整数n和m,均有f(mn)=f(m)f(n),就称为完全积性函数。
(欧拉函数就是一个积性函数证明:http://www.cnblogs.com/372465774y/archive/2012/10/16/2726282.html)
定理:
1.如果f是一个积性函数,对任意正整数n有素数幂分解n=p1a1 * p2a2 * .... *psas,那么f(n)=f(p1a1)*f(p2a2)*...*f(psas)。
2.如果p是素数,那么φ(n)=p-1;反之如果p是一个正整数且满足φ(p)=p-1,那么p是素数。
3.设p是素数,a是一个正整数,那么φ(pa)=pa-pa-1。
证明:比pa小的数有pa-1个,因为pa只有一个素因子p,其中与p不互质的有pa-1-1(分别是1*p,2*p,3*p....(pa-1-1)*p )
所以φ(pa)=(pa-1)-(pa-1-1)=pa-pa-1 证毕。
4.设n和m是互质的正整数,那么φ(nm)=φ(n)φ(m) (因为欧拉函数是积性函数嘛,上面有证明)。
5.设n=p1a1 * p2a2 * .... *pkak 为正整数n的素数幂分解,那么
φ(n)=n * (1-1/p1)*(1-1/p2)*....*(1-1/pk) (算法的核心)
证明:由定理4可知φ(n)=φ(p1a1)*φ(p2a2)*.....*φ(pkak)
再由定理3得φ(n)=(p1a1-p1a1-1)*(p2a2-p2a2-1)*.....*(pkak-pkak-1)
提取因素得φ(n)=p1a1 (1-1/p1)*p2a2(1-1/p2)*pkak(1-1/pk)
所以φ(n)=n * (1-1/p1)*(1-1/p2)*....*(1-1/pk) 证毕。
推论:当n为奇数时,有φ(2n)=φ(n);
证明:设n=p1a1 * p2a2 * .... *pkak(假设p1是2) 则 φ(n)=n * (1-1/p1)*(1-1/p2)*....*(1-1/pk)
那么2n=p1a1+1 * p2a2 * .... *pkak 即φ(2n)=(p1a1+1-p1a1)*(p2a2-p2a2-1)*.....*(pkak-pkak-1)
=p1a1 (p1-1)*p2a2(1-1/p2)*pkak(1-1/pk)
=n * (p1-1)*(1-1/p2)*....*(1-1/pk)
=n *(1-1/p2)*....*(1-1/pk)
因为n为奇数所以没有2这个素因子,即a1=0. 所以φ(n)=n *(1-1/p2)*....*(1-1/pk)=φ(2n) 证毕。
6.设n是一个大于2的正整数,那么φ(n)是偶数
证明:因为φ(n)=(p1a1-p1a1-1)*(p2a2-p2a2-1)*.....*(pkak-pkak-1)
情况一:n有2这个素因子时,piai-piai-1(令pi=2)一定是偶数(偶数减偶数嘛)φ(n)是一个偶数的倍数当然是偶数了。
情况二 : n没有2这个素因子,一定存在一个奇素因子,piai-piai-1为偶数(因为 p^a与p^(a-1) 均为奇数)
7.∑d|nφ(d)=n (即n的因子的欧拉函数值之和为n)
证明:
情况一:n=1时显然成立
情况二:n≠1时,
定理基本介绍完了,我们来看代码:
如果根据定理5直接实现:
int phi(int n) { int rea=n; for(int i=2;i<=n;i++) { if(n%i==0)//找到素因子 { rea=rea/i*(i-1); while(n%i==0)//把该素因子全部约掉 n/=i; } } return rea; }
时间复杂度为O(n),还可以优化降到O(√n),因为任何一个合数都至少有一个不大于√n的素因子,所以只需要遍历√n即可
int phi(int n) { int rea=n; for(int i=2;i*i<=n;i++)//变化的地方 { if(n%i==0) { rea=rea/i*(i-1); while(n%i==0) n/=i; } } if(n>1)//有可能有一个大于√n素因子 rea=rea/n*(n-1); return rea; }
如果最后n>1,为什么一定是一个大于√n的素因子。简单说下,因为不可能是两个及以上素因子的乘积。因为倒数第二个素因子一定小于√n。