定义:欧拉函数φ(n),表示小于或等于n的数中与n互质的数的数目。
性质:
1) φ(1) = 1
2) 若n是质数p的k次幂,φ(n) = p^k - p^(k-1) = (p - 1)*p^(k - 1)
因为p为质数,所以与n不互质的数只有p的倍数,一共有p^(k-1)个,由此可得。
3) 若m, n互质,φ(m*n) = φ(m) * φ(n)
求法:
1、对任意一个正整数n,pi为其第 i 个质因子,一共 j 个:
φ(n) = (p1 - 1)*p1^(k1 - 1) * … * (pj - 1)*pj^(kj - 1)
= n * (1 - 1/p1) * … * (1 - 1/pj)
可以根据这条式子,我们可以使用类似素数筛法的方式来求解:
int phi[MAXN];
void getPhi(int n)
{
for(int i=1;i<n;i++) //初始化为自身
phi[i]=i;
for(int i=2;i<n;i++)
if(phi[i]==i)
{
phi[i]=i-1;
for(int j=i*2;j<n;j+=i)
phi[j]=phi[j]/i*(i-1);
}
}
2、上面那种方法似乎慢了一点,根据欧拉函数的性质,我们可以有如下递推式:
p 为 n 最小质因数,根据上面性质2)、3),我们可以得到下面两条递推公式:
(1) n % (p^2) == 0 , φ(n) = φ(n/p) * p ;
此时n/p与p存在公因子p,根据性质2),因为φ(n/p)中必然已经计算过p-1了,那么每多一维p,φ(p)需要乘上p。
(2) n % (p^2) != 0 , φ(n) = φ(n/p) * (p-1) ;
此时n/p与p互质,所以根据性质3),并且φ(p)=p-1,可以得到。
这使得我们需要先求出n的最小质因数:
int phi[MAXN];
void getPhi(int n)
{
int minDiv;
for(int i=1;i<n;i++)
phi[i]=i;
for(int i=2;i*i<n;i++) //最小质因数
if(phi[i]==i)
{
for(int j=i*i;j<n;j+=i)
phi[j]=i;
}
phi[1]=1;
for(int i=2;i<n;i++)
{
minDiv=phi[i];
if((i/phi[i])%phi[i]==0)
phi[i]=phi[i/phi[i]]*phi[i];
else
phi[i]=phi[i/phi[i]]*(phi[i]-1);
}
}
时间复杂度为O( log(n) * n )
欧拉函数的重要性质:
1、如果n为正整数且a是一个与n互质的数,那么:
a ^ φ(n) ≡ 1 (mod n)
这个性质称为欧拉定理,其实是费马小定理的一个升级版。
2、当模m有原根时,有φ(φ(m))个原根。