欧拉函数,一般写作 φ 或者 ϕ。φ(x) 表示的是 [1,x] 区间内有多少个数与 x 互质(最大公因数为 1
)。
只有不是 x 的质因子的倍数的数才和 x 互质;
第一个质因子的倍数共有 x×pi1 个,那么和第一个质因子互质的数就有 x×pipi−1 个;
这 x×pipi−1 个数里,和第二个质因子互质的个数又有 x×pipi−1 个;
一直乘下去,便得到 φ(x)=xi=1∏npipi−1。
- 性质 3:φ(xy)=φ(x)φ(y)×φ(gcd(x,y))gcd(x,y)
考虑 φ(x)=xi=1∏npipi−1,观察到 φ(x)φ(y)=xyi=1∏mpipi−1 多乘了 gcd(x,y) 的质因子的 pipi−1,所以要除掉 gcd(x,y)φ(gcd(x,y))。
- 性质 4:若 p 是 x 的一个质因子,φ(xp)=φ(x)⋅p。
若 gcd(x,y)=1,gcd(x,y+x)=1。
- 性质 5:d∣n∑φ(d)=n
设 n 个分数 n1n2n3...nn,全部化到最简后,分母显然全部是 n 的因子,而分母 d 有 φ(d) 个,又因为分母总共有 n 个,所以得证。
以上性质的具体证明可以看这篇文章。
有了这些特质,我们便可以结合欧拉筛来实现 O(n) 求 x∈[1,n] 的 φ(x) 了。
代码如下:
int fhi[100005];
bool nop[100005];
int tot,prime[100005];
int n;
void init()
{
nop[0]=true; // 0 不是质数
nop[1]=true; // 1 不是质数
fhi[1]=1; // 1 和 1 互质(
for(int i=2;i<=n;i++)
{
if(!nop[i])
{
prime[++tot]=i;
fhi[i]=i-1; // 是一个质数,fhi(i) 满足性质 1
}
for(int j=1;j<=tot;j++)
{
if(i*prime[j]>n)
{
break;
}
nop[i*prime[j]]=true;
if(i%prime[j]==0)
{
fhi[i*prime[j]]=fhi[i]*prime[j]; // prime[j] 是 i 的一个质因子,满足性质 4
break;
}
fhi[i*prime[j]]=fhi[i]*fhi[prime[j]]; // i 和 prime[j] 互质,满足性质 3
}
}
}
练习题目
P2158 [SDOI2008] 仪仗队
P2398 GCD SUM
P1390 公约数的和
P2568 GCD
LOJ 6179 Pyh 的求和