ϕ(x):1到x中与x互质的数的个数。
欧拉函数公式:若x可以被分解素数分解为 x=ap11ap22...apkk 则
ϕ(x)=x(1−1a1)(1−1a2)...(1−1ak)
关于这个公式的理解,可以先考虑只有一个素数因子的形式。
若 x=ap ,则1~x中能被a整除的数分别为 a,2a,3a,...,ap ,共 xa 个,剩下的是不能被a整除的数,自然的就和x互质。因此容易得到 ϕ(x)=x−xa=x(1−1a)
从上面的例子可以看出,a的倍数其实是在1~x之间平均分布的。这样的平均分布适用于任何的数的倍数。
当一个数有多个素数因子的时候,可以利用这些因子的倍数是各自平均分布的性质,依次累乘上 (1−1p) .相当于筛去了p的倍数。
举个例子:30=2·3·5
这是因为被筛去的数是平均分布的,则剩下的数中,为另一个素数的倍数也是平均分布的。
当 (n,m)=1时,ϕ(nm)=ϕ(n)ϕ(m)
这表明了欧拉函数是积性函数。利用上面的欧拉函数公式,把n,m分别素因数分解,即可得其正确。
当x为素数时, ϕ(x)=x−1 ;当x为奇数时, ϕ(2x)=x−1 .
当p为素数时,
(1). 当 p∣n且p2∤n , ϕ(n)=ϕ(np)(p−1) ;
(2). 当 p∣n且p2∣n , ϕ(n)=ϕ(np)p ;
第一种情况, (np,p)=1 由性质1可得成立;
第二种情况,利用 ϕ(n)和ϕ(np) 展开式相除得到p,也可得成立。
∑d|nϕ(d)=n
首先,有 (n,m)=1 时, ∑d|mnϕ(d) 是积性函数,即 ∑d|mnϕ(d)=(∑d|mϕ(d))(∑d|nϕ(d)) 可以利用乘法原理想清楚这个式子的正确性。
其次,考虑单个素因子幂的情况。当 n=pa ,则 ∑d|nϕ(d)=ϕ(1)+ϕ(p)+ϕ(p2)+...+ϕ(pa) =1+(p−1)+p(p−1)+...pa−1(p−1) =1+(p−1)pa−1p−1=pa
则当n被拆分为多个素因子的幂的形式,根据前两条即证。
给n,求 ϕ(n)
按照欧拉函数公式分解出所有n的质因子即可计算得到答案。复杂度O( n√ )
int phi(int n)
{
int ans = n;
for(int i = 2;i*i <= n;i++)if(n % i == 0)
{
ans -= ans/i;
while(n % i == 0)
n /= i;
}
if(n != 1)
ans -= ans/n;
return ans;
}
给素数p,求原根,即 ϕ(p−1)
关于原根的知识之后再补充。
给n,求ans[n]。其中ans[n]=ans[n-1]+phi[n],且n的范围比较大,在10的6次以内。则考虑打表解决。
先得到能整除i的最小正整数md[i](一定是个素数),再利用性质3,得到phi[i]
void set()
{
for(int i = 0;i < N;i++)
md[i] = i;
for(int i = 2;i < N;i++) if(md[i] == i)
{ //也可以只让2和奇数进来
for(int j = i;j < N;j += i) if(md[j] == j)
md[j] = i; //只要最小的,不要被覆盖
}
for(int i = 2;i < N;i++)
{
if(md[i] == i)
phi[i] = i-1;
else
{
phi[i] = phi[i/md[i]];
if(i/md[i] % md[i])
phi[i] *= md[i]-1;
else
phi[i] *= md[i];
}
}
}
后面这种写法比较简短,也可以根据性质3来理解。
void set()
{
for(int i = 0;i < N;i++)
phi[i] = i;
for(int i = 2;i < N;i += 2)
phi[i] /= 2; //质数为2先处理一遍
for(int i = 3;i < N;i += 2) if(phi[i] == i)
{ //处理奇因子
for(int j = i;j < N;j += i)
phi[j] = phi[j]/i*(i-1);
}
}
给n,求ans[i] = ans[i-1] + 2*phi[i]