今天我们来学一下欧拉函数。
定义:欧拉函数是小于n的数中与n互质的数的数目。例如φ(8)=4,因为1,3,5,7均和8互质。
欧拉函数的通式为:,其中pi表示x的质因数。特别声明,φ(1)=1。
注意:每种质因数只一个。比如12=223那么φ(12)=12*(1-1/2)*(1-1/3)=4。
其中还有比较特殊的几个。
1:如果x是a^k,那么----除a的倍数外都与他互质。
2.如果n是奇数,那么.
3.如果n是质数,那么,即所有小于n的数都与他互质。
证明这个坑先留着吧,以后再来填。
计算时phi(x)=x(1-1/p1)…(1-1/pi)中的x(1-1/pi)可以转化为x/pi*(pi-1)用来避免小数的产生,同时先除后乘可以避免溢出。
对于单个数x的欧拉函数phi(x)计算方法如下:
从2开始枚举n是否为x的因数,如果是,则ans=ans/n*(n-1),然后一直除n。因为n是x的因数,所以也不会有相除后变成小数的情况发生.
一直枚举到x被除到了1说明已经除完了。
单个数的欧拉函数实现代码:
int euler_phi(int n)
{
int res=n;
for(int i=2;i*i<=n;i++)
{
if(n%i==0)
{
res=res/i*(i-1);
for(;n%i==0;n/=i);
}
if(n!=1)
res=res/n*(n-1);
return res;
}
}
和质数的筛法类似,欧拉函数也有一个复杂度是线性的筛,方法如下:
先将每个数对应的euler值euler[i]初始化为自己,接着从2开始枚举i<=,对所有小于maxn的i的倍数ki都进行一次euler[ki]=euler[ki]/i*(i-1)操作即可.
线性欧拉函数实现代码:
void euler_phi2()
{
for(int i=0;i<maxn;i++)
euler[i]=i;
fro(int i=2;i<maxn;i++)
{
if(euler[i]==i)
{
for(int j=i;j<maxn;j+=i)
{
euler[j]=euler[j]/i*(i-1);
}
}
}
}