莫比乌斯反演-OIWiki
数论分块:对于
⌊
n
i
⌋
\lfloor \frac{n}{i} \rfloor
⌊in⌋ ,要找一个最大的值
j
j
j ,使得
j
=
⌊
n
i
⌋
j=\lfloor \frac{n}{i} \rfloor
j=⌊in⌋ 。这个
j
=
⌊
n
⌊
n
i
⌋
⌋
j=\lfloor \frac{n}{\lfloor \frac{n}{i} \rfloor} \rfloor
j=⌊⌊in⌋n⌋ 。由于
⌊
n
i
⌋
\lfloor \frac{n}{i} \rfloor
⌊in⌋ 最多有
n
\sqrt n
n 种取值,因此可以分成
n
\sqrt n
n 个块。
狄利克雷卷积:
(
f
∗
g
)
(
n
)
=
∑
d
∣
n
f
(
d
)
g
(
n
d
)
(f *g)(n)=\sum_{d|n}f(d)g(\frac{n}{d})
(f∗g)(n)=∑d∣nf(d)g(dn) 。
可以推出
μ
∗
1
=
∑
d
∣
n
μ
(
d
)
=
∑
i
=
0
k
(
−
1
)
k
(
k
i
)
\mu * 1= \sum_{d|n}\mu(d) = \sum_{i=0}^k(-1)^k\tbinom{k}{i}
μ∗1=∑d∣nμ(d)=∑i=0k(−1)k(ik) ,假设
k
k
k 为
n
n
n 的不同质因子个数。
由
(
x
+
y
)
k
=
∑
i
=
0
k
x
i
y
k
−
i
(
k
i
)
(x+y)^k=\sum_{i=0}^kx^iy^{k-i}\tbinom{k}{i}
(x+y)k=∑i=0kxiyk−i(ik) ,当
x
=
−
1
,
y
=
1
x=-1,y=1
x=−1,y=1 时,得到
0
k
=
∑
i
=
0
k
(
−
1
)
k
(
k
i
)
0^k=\sum_{i=0}^k(-1)^k\tbinom{k}{i}
0k=∑i=0k(−1)k(ik) ,而
0
k
0^k
0k 当
k
=
1
k=1
k=1 时为
1
1
1 ,其他时候为
0
0
0 。因此
μ
∗
1
=
ε
=
[
n
=
1
]
\mu * 1=\varepsilon=[n=1]
μ∗1=ε=[n=1] 。
由上可知,
[
g
c
d
(
i
,
j
)
=
1
]
=
∑
d
∣
g
c
d
(
i
,
j
)
μ
(
d
)
[gcd(i,j)=1]=\sum_{d|gcd(i,j)} \mu (d)
[gcd(i,j)=1]=∑d∣gcd(i,j)μ(d) 。
莫比乌斯反演:
g
(
n
)
=
∑
d
∣
n
f
(
d
)
g(n) = \sum_{d|n}f(d)
g(n)=∑d∣nf(d) ->
f
(
n
)
=
∑
d
∣
n
μ
(
d
)
g
(
n
d
)
f(n)=\sum_{d|n} \mu (d) g (\frac{n}{d})
f(n)=∑d∣nμ(d)g(dn) 。
证明:
g
=
f
∗
1
g = f *1
g=f∗1 。两边都卷积上
μ
\mu
μ 时,
μ
∗
g
=
f
∗
1
∗
μ
\mu * g = f * 1 * \mu
μ∗g=f∗1∗μ 。由于狄利克雷卷积满足结合律和交换律且
μ
∗
1
=
ε
\mu * 1 = \varepsilon
μ∗1=ε , 则
f
∗
1
∗
μ
=
f
∗
ε
=
f
f * 1 * \mu = f * \varepsilon = f
f∗1∗μ=f∗ε=f,因此
f
=
μ
∗
g
f=\mu * g
f=μ∗g 。莫比乌斯反演得证。
例题:
BZOJ-2301:
求:
∑
i
=
x
n
∑
j
=
y
m
[
g
c
d
(
i
,
j
)
=
k
]
\sum_{i=x}^n\sum_{j=y}^m[gcd(i,j)=k]
i=x∑nj=y∑m[gcd(i,j)=k]
可以转为求
∑
i
=
1
n
∑
j
=
1
m
[
g
c
d
(
i
,
j
)
=
k
]
\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=k]
∑i=1n∑j=1m[gcd(i,j)=k] 然后容斥求答案。前式可以转化为:
∑
i
=
1
n
/
k
∑
j
=
1
m
/
k
[
g
c
d
(
i
,
j
)
=
1
]
\sum_{i=1}^{n/k}\sum_{j=1}^{m/k}[gcd(i,j)=1]
∑i=1n/k∑j=1m/k[gcd(i,j)=1] 。然后可以转为为
∑
i
=
1
n
/
k
∑
j
=
1
m
/
k
∑
d
∣
g
c
d
(
i
,
j
)
μ
(
d
)
\sum_{i=1}^{n/k}\sum_{j=1}^{m/k} \sum_{d|gcd(i,j)} \mu (d)
∑i=1n/k∑j=1m/k∑d∣gcd(i,j)μ(d) 。假设
n
<
m
n<m
n<m ,将
d
d
d 提到最外面得到:
∑
d
=
1
n
/
k
μ
(
d
)
∑
i
=
1
n
/
k
[
i
≡
0
(
m
o
d
d
)
]
∑
j
=
1
m
/
k
[
j
≡
0
(
m
o
d
d
)
]
\sum_{d=1}^{n/k} \mu (d)\sum_{i=1}^{n/k} [i \equiv 0 \pmod{d}] \sum_{j=1}^{m/k} [j \equiv 0 \pmod{d}]
∑d=1n/kμ(d)∑i=1n/k[i≡0(modd)]∑j=1m/k[j≡0(modd)] 。后面两项就是求有多少个
i
i
i 和
j
j
j 是
d
d
d 的倍数,因此可以转化为
∑
d
=
1
n
/
k
μ
(
d
)
×
(
n
/
(
k
d
)
)
×
(
m
/
(
k
d
)
)
\sum_{d=1}^{n/k} \mu (d) \times (n/(kd)) \times (m/(kd))
∑d=1n/kμ(d)×(n/(kd))×(m/(kd)) 。然后就可以求出
μ
\mu
μ 的前缀和,然后数论分块来做。
#include <bits/stdc++.h>
using namespace std;
const int N = 5e4+7;
int mu[N], p[N];
bool nop[N];
void init() {
int tot=0;
mu[1]=1;
for(int i=2; i<N; ++i) {
if(!nop[i]) {
p[++tot]=i;
mu[i]=-1;
// 单个素数为-1
}
for(int j=1; j<=tot&&i*p[j]<N; ++j) {
nop[i*p[j]] = 1;
if(i%p[j]==0) {
mu[i*p[j]] = 0;
//存在两个相同的素数因子,为0
break;
}
mu[i*p[j]] = -mu[i]; // 乘-1
}
}
// 求mu前缀和。
for(int i=1; i<N; ++i) mu[i]+=mu[i-1];
}
int solve(int n, int m) {
int res = 0;
for(int i=1, j; i<=min(n, m); i=j+1) {
j = min(n/(n/i), m/(m/i));
// [i, j]分块计算
res += (mu[j]-mu[i-1])*(n/i)*(m/i);
}
return res;
}
int main() {
int a, b, c, d, k, T;
scanf("%d", &T);
init();
while(T--) {
scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
int res = solve(b/k, d/k);
res -= solve((a-1)/k, d/k);
res -= solve(b/k, (c-1)/k);
res += solve((a-1)/k, (c-1)/k);
printf("%d\n", res);
}
return 0;
}