1 欧拉函数的定义
欧拉函数:对于一个数x,小于x的整数中与x互质的数的个数就是欧拉函数,用φ(x)来表示。特殊的φ(1)=1.
2 通项公式
Pi为x的所有质因数。
3 单个数的欧拉求法
ll Euler(ll x){
ll k=x;
for(ll i=2;i*i<=x;i++)
{
if(x%i==0) //这里的i都是x的质因数
{
k=k/i*(i-1);
while(x%i==0) //将包含的当前质因数都除掉,保证下一个除的数还是它的质因数。
{
x/=i;
}
}
}
if(x>1) //如果最后x还不为0,还有剩下的质因子,比如它本身。
k=k/x*(x-1);
return k;
}
4 欧拉打表
欧拉函数的定义式:φ(x)=x*(1-1/p1)(1-1/p2)(1-1/p3)*(1-1/pk) p1.p2.p3.p4…pk都是x的质因数。
则我们可以从素数出发,如果要打一个大小为N的表,开一个数组先赋初值为自身,然后用类似于素数打表的方法,从2遍历到N,先判断是不是素数,若伪素数就给所有这个素数的倍数乘上(1-1/素数) ,这样处理过后就得到了欧拉表,并且同时还筛出了素数…?
时间复杂度为O(n*log(n))
void getphi(){
for(int i=1;i<=n;i++)
{
phi[i]=i;
}
for(int i=2;i<=n;i++)
{
if(phi[i]==i)
{
for(int j=i+i;j<=n;j+=i)
phi[j]=phi[j]/i*(i-1);
}
}
}
5 欧拉函数线性筛
比上面的效率更高,可以在线性时间内处理完。
这里用到了三条结论(从别的博客学到的…)
下面P为质数
- Phi ( P ) = P-1。
这个比较容易,对于素数P来说,它只有1和P两个因数,所以不与它互质的数只有P。 - 如果i mod p = 0, 那么Phi(i * P)=P * Phi(i)
这个证明就搞不懂了… - 若i mod P ≠0, 那么Phi(i * P)=Phi(i) * (P-1)
欧拉函数为积性函数,所以Phi(i * P)=Phi(i) * Phi( P ),又由于第一条结论,所以Phi(i * P)=Phi(i) * (P-1)。
int prime[maxn],Phi[maxn];
bool flag[maxn];
int tot;
void getPhi(){
Phi[1]=1;
for(int i=1;i<=n;i++)
{
if(!flag[i])
{
prime[tot++]=i;
Phi[i]=i-1; //第一条结论
}
for(int j=0;j<tot;j++)
{
if(prime[j]*i>n) break;
flag[prime[j]*i]=1;
if(i%prime[j]==0)
{
Phi[i*prime[j]]=Phi[i]*prime[j];//第二条结论
break;
}
else
Phi[i*prime[j]]=Phi[i]*(prime[j]-1);//第三条结论
}
}
}