终于学了一波莫比乌斯反演,感觉一些技巧还是容易忘的,记一下方便回顾。
莫比乌斯函数
定义
莫比乌斯函数 μ(n) 的定义:
设 n=p1k1⋅p2k2⋅⋯⋅pmkm,其中 p 为素数,则定义如下:
μ(n)=⎩⎪⎪⎪⎨⎪⎪⎪⎧1(−1)m0n=1i=1∏mki=1otherwise(ki>1)可知有平方因子的数的莫比乌斯函数值为 0。
性质
性质一:莫比乌斯函数是积性函数。
μ(a)μ(b)=μ(a⋅b),a⊥b应用:根据这一性质,我们可以采取线性筛法,用 O(n) 的时间预处理出所有 [1,n] 内的莫比乌斯函数值。
质数的值为 −1,如果一个数存在某个质因子的指数不为 1,那么它将会被筛为 0(值得注意的是,只有数存在最小质因子的指数大于 1 时,它才会被直接筛为 0,其余的情况是由 μ(d)=−μ(i) 来完成的)。
每个数仅被其最小质因子筛去,故复杂度为 O(n)。
void sieve() {
fill(isPrime, isPrime + maxn, 1);
mu[1] = 1, num = 0;
for (int i = 2; i < maxn; ++i) {
if (isPrime[i]) primes[num++] = i, mu[i] = -1;
static int d;
for (int j = 0; j < num && (d = i * primes[j]) < maxn; ++j) {
isPrime[d] = false;
if (i % primes[j] == 0) {
mu[d] = 0;
break;
} else mu[d] = -mu[i];
}
}
}
性质二:
d∣n∑μ(d)=[n=1]证明:当 n=1 时有 μ(1)=1,显然成立。否则设 n=p1k1⋅p2k2⋅⋯⋅pmkm,d=p1x1⋅p2x2⋅⋯⋅pmxm 根据 μ 的定义,只需考虑 xi=0 或 xi=1 的情况。我们设 d 中存在 r 个 xi 为 1,那么有:
d∣n∑μ(d)=r=0∑m(rm)(−1)r(n≠1)根据二项式定理:
(x+y)n=k=0∑n(kn)xn−kyk我们令 x=1,y=−1,即得证:
r=0∑m(rm)(−1)r=(1−1)m=0(n≠1)此公式运用的很多,在求 gcd=1 或是用杜教筛求前缀和的时候都用的到。
莫比乌斯反演
公式
如果 f(n),g(n) 是数论函数,且满足:
f(n)=d∣n∑g(d)则有莫比乌斯反演:
g(n)=d∣n∑μ(dn)f(d)=d∣n∑μ(d)f(dn)证明:
===d∣n∑μ(d)f(dn)d∣n∑μ(d)i∣dn∑g(i)i∣n∑g(i)k∣in∑μ(k)g(n)根据莫比乌斯函数的性质 2,可知当且仅当 i=n 时和式的值为 g(n),否则为 0。
变形
f(i)=d=1∑⌊in⌋g(d⋅i)⇒g(i)=d=1∑⌊in⌋f(d⋅i)μ(d)证明就略过了,与上面的证明大同小异,可以做为练习加深理解。
应用
所有和式默认 n≤m,不满足则交换。
求 gcd = k 的个数
i=1∑nj=1∑m[gcd(i,j)=k]设 f(k) 为 gcd(i,j)=k 的个数,g(k) 为满足 k∣gcd(i,j) 的对数,则有以下关系:
g(k)=x=1∑⌊kn⌋f(k⋅x)我们只需快速求出 g(k),可知,如果 i,j 能被 k 整除,那么它们可以写成 i=k⋅x1,j=k⋅x2 的形式,我们只需求有多少对 x1,x2 即可,可得:
g(k)=⌊kn⌋⌊km⌋根据莫比乌斯反演的变形,可求得 f(k):
f(k)=x=1∑⌊kn⌋μ(x)g(k⋅x)=x=1∑⌊kn⌋μ(x)⌊kxn⌋⌊kxm⌋显然 f(k) 就是答案,暴力求是 O(n) 的。如何快速求?这里很重要的思想就是分块,⌊dn⌋ 有至多 O(√n) 个取值。
证明:当 1≤d<√n 时,由于 d 只有 √n 个,所以 ⌊dn⌋ 也只有至多 √n 个取值。
当 √n≤d≤n 时,由于 ⌊dn⌋ 小于 √n,所以 ⌊dn⌋ 也只有至多 √n 个取值。
⌊dn⌋ 有至多 O(√n) 个取值,证明完毕。
同理 ⌊dm⌋ 也只有至多 √m 个取值,又因为取值是连续的,所以 ⌊kxn⌋ 与 ⌊kxm⌋ 同时不变的段数有 O(√n+√m) 个。
例:n=32,m=40,k=2,红色为相等的段。
对于相等的段,我们求取 μ 的前缀和,即可批量计算这一个段的答案。
ll F(int n, int m, int d) {
if (n > m) swap(n, m);
ll ans = 0;
n /= d, m /= d;
for (int i = 1, last = 1; i <= n; i = last + 1) {
last = min(n / (n / i), m / (m / i));
ans += (ll)(sum[last] - sum[i - 1]) * (n / i) * (m / i);
}
return ans;
}
对于位置 i,找到下一个相等的位置的代码为 min(n / (n / i), m / (m / i))
。对于 n 来说,我们要找到最大的 j,满足:
⌊jn⌋≥⌊in⌋可以拆掉左边的底:
jn≥⌊in⌋继续化简:
j≤⌊⌊in⌋n⌋所以 j=⌊⌊in⌋n⌋,对 m 同理,取两个 j 最小值即为都不变的段 [i,j]。
总之,复杂度为 O(√n+√m)。
这个 f(k) 以及分块非常重要,几乎题题都会用到。
gcd(i, j) 的幂
i=1∑nj=1∑mgcd(i,j)kmod(109+7)按照我们刚刚的技巧,枚举最大公约数 d 然后转换为可分块的形式:
i=1∑nj=1∑mgcd(i,j)k=d=1∑ndki=1∑nj=1∑m[gcd(i,j)=d]=d=1∑ndkx=1∑⌊dn⌋μ(x)⌊dxn⌋⌊dxm⌋到这里可以分套分块 O((√n)2)=O(n),如果多组询问怎么办呢?另一重要技巧就是枚举 dx,你可能会疑惑,d,x 都没定呢,怎么枚举 dx?实际上我们枚举的是乘积,让 dx 为定值,这个情况下再枚举 d。
原式可化为:
T=1∑n⌊dxn⌋⌊dxm⌋d∣n∑dkμ(dT)这样的求出答案是正确的吗?我们知道之前一步的式子是:∑d=1ndk∑x=1⌊dn⌋μ(x)⌊dxn⌋⌊dxm⌋。
显然只要 d 以及 x 定了,式子的一项也就定了,于是原式也可以写成;
(d,x)∑dkμ(x)⌊dxn⌋⌊dxm⌋只要我们能枚举出所有的二元组 (d,x),并把对应项乘起来,就是正确的。
如果设 f(n)=∑d∣ndkμ(dT),则我们只需要求 f 的一个前缀和就可以 O(√n) 回答询问了。
发现 dk 是积性函数,根据莫比乌斯反演的性质,f 也是一个积性函数,我们可以线筛 O(n) 求出答案。
怎么线筛?如果对于积性函数 f 来说,f(pk),p is a prime 能 O(1) 求出的话,那么就可以 O(n) 预处理了,详见 线性筛法与积性函数。
所以我们要想办法快速处理 f(pk),通常要分解质因数来考虑。
这里化一下 f:
f(n)=d∣n∑dkμ(dT)=pi∏f(pixi)=pi∏(pixi⋅μ(1)+pik(xi−1)⋅μ(pi))=pi∏pik(xi−1)(pik−1)总复杂度:O(n+T√n)。
其他技巧
题目太多了,我懒得写了。好像不少题目都是与“求 gcd(i,j) 的幂”差不多的方法,最后都变成了线筛预处理积性函数了,那就不写了,记一下化简式子中可能用到的小技巧吧。
如果 d(n) 为 n 的约数个数,则:
d(nm)=i∣n∑j∣m∑[gcd(i,j)=1]证明:设 nm=p1x1⋅p2x2⋅p3x3⋯pkxk,且 n=p1y1⋅p2y2⋅p3y3⋯pkyk,则 m=p1x1−y1⋅p2x2−y2⋅p3x3−y3⋯pkxk−yk。
设 i=p1a1⋅p2a2⋅p3a3⋯pkak,j=p1b1⋅p2b2⋅p3b3⋯pkbk,要使 gcd(i,j)=1,必然有 a1 或 b1 为 0,如果 a1 为 0,那么 b1 有 xi−y1+1 种取值;如果 b1 为 0,那么 a1 有 y1+1 种取值,一共有 x1+1 种取值,对于 xi 也如此。
所以满足条件的 i,j 对数为 ∏(xi+1),与约数定理给出的形式一样,得证。
总结
还没写完怎么就总结了
莫比乌斯反演一般来说套路比较固定,看到两个求和符号,基本上就逃不开莫比乌斯了。
求和的东西可能不同,但是一般都与 gcd 有关,枚举 gcd,再使用 gcd=k 的个数 + 分块一般能 O(n),将后面的部分提前 + 积性函数预处理 + 分块一般能单组 O(√n)。
积性函数有时不好数学证明,那么可以打表来验证,重点关注质数,质数的幂的值。
还有如果 n,m 比较大的,可能需要使用杜教筛处理一下前缀和,需要一些数学功底来推导。
杜教筛我可能会新开一个笔记(填坑)。