题
意
\large题意
题意
题目链接
求
∑
i
=
1
a
∑
j
=
1
b
[
g
c
d
(
i
,
j
)
=
d
]
求\sum_{i=1}^{a} \sum_{j=1}^{b} [gcd(i, j) = d]
求∑i=1a∑j=1b[gcd(i,j)=d]
题
解
\large题解
题解
莫
比
乌
斯
函
数
有
个
性
质
莫比乌斯函数有个性质
莫比乌斯函数有个性质
∑
d
∣
n
μ
(
d
)
=
[
n
=
1
]
\sum_{d|n} \mu(d) = [n = 1]
d∣n∑μ(d)=[n=1]
我
们
使
用
g
c
d
(
i
,
j
)
代
替
n
得
到
如
下
的
式
子
我们使用gcd(i, j)代替n得到如下的式子
我们使用gcd(i,j)代替n得到如下的式子
∑
d
∣
g
c
d
(
i
,
j
)
μ
(
d
)
=
[
g
c
d
(
i
,
j
)
=
1
]
\sum_{d|gcd(i, j)} \mu(d) = [gcd(i, j) = 1]
d∣gcd(i,j)∑μ(d)=[gcd(i,j)=1]
接
下
来
我
们
来
推
式
子
,
我
们
假
设
a
<
b
接下来我们来推式子, 我们假设 a < b
接下来我们来推式子,我们假设a<b
原 式 = ∑ i = 1 a ∑ j = 1 b [ g c d ( i , j ) = d ] = ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = 1 ] ( 令 n = a / d , m = b / d ) = ∑ i = 1 n ∑ j = 1 m ⋅ ∑ k ∣ g c d ( i , j ) μ ( k ) = ∑ k = 1 n μ ( k ) ⋅ ∑ i = 1 n ∑ j = 1 m [ k ∣ g c d ( i , j ) ] = ∑ k = 1 n μ ( k ) ⋅ ⌊ n k ⌋ ⌊ m k ⌋ = ∑ k = 1 a / d μ ( k ) ⋅ ⌊ a d k ⌋ ⌊ b d k ⌋ \begin{aligned} \qquad\qquad\qquad 原式 &=\sum_{i=1}^{a} \sum_{j=1}^{b} [gcd(i, j) = d] \\ &= \sum_{i=1}^{n} \sum_{j=1}^{m} [gcd(i, j) = 1] \ \ (令n = a/d, m = b/d)\\ &= \sum_{i=1}^{n} \sum_{j=1}^{m} \cdot \sum_{k|gcd(i, j)} \mu(k) \\ &= \sum_{k=1}^{n} \mu(k) \cdot \sum_{i=1}^{n} \sum_{j=1}^{m}[k | gcd(i, j)]\\ &= \sum_{k=1}^{n} \mu(k) \cdot \lfloor \frac{n}{k} \rfloor \lfloor \frac{m}{k} \rfloor \\ &= \boxed{\sum_{k=1}^{a/d} \mu(k) \cdot \lfloor \frac{a}{dk} \rfloor \lfloor \frac{b}{dk} \rfloor }\\ \end{aligned} 原式=i=1∑aj=1∑b[gcd(i,j)=d]=i=1∑nj=1∑m[gcd(i,j)=1] (令n=a/d,m=b/d)=i=1∑nj=1∑m⋅k∣gcd(i,j)∑μ(k)=k=1∑nμ(k)⋅i=1∑nj=1∑m[k∣gcd(i,j)]=k=1∑nμ(k)⋅⌊kn⌋⌊km⌋=k=1∑a/dμ(k)⋅⌊dka⌋⌊dkb⌋
那 么 我 们 可 以 在 O ( N ) 的 时 间 复 杂 度 内 来 计 算 出 这 个 式 子 , 但 是 由 于 有 多 组 数 据 , 因 此 我 们 需 要 整 除 分 块 那么我们可以在O(N)的时间复杂度内来计算出这个式子, 但是由于有多组数据,\\因此我们需要整除分块 那么我们可以在O(N)的时间复杂度内来计算出这个式子,但是由于有多组数据,因此我们需要整除分块1
上
面
的
结
论
,
我
们
可
以
换
一
种
方
式
来
推
导
,
这
里
使
用
了
莫
比
乌
斯
反
演
上面的结论,我们可以换一种方式来推导,这里使用了莫比乌斯反演
上面的结论,我们可以换一种方式来推导,这里使用了莫比乌斯反演2
我
们
设
f
(
d
)
=
g
c
d
(
i
,
j
)
为
d
的
个
数
我们设f(d) = gcd(i, j)为d的个数
我们设f(d)=gcd(i,j)为d的个数
f
(
d
)
=
∑
i
=
1
a
∑
j
=
1
b
[
g
c
d
(
i
,
j
)
=
d
]
f(d) = \sum_{i=1}^{a} \sum_{j=1}^{b} [gcd(i, j) = d]
f(d)=i=1∑aj=1∑b[gcd(i,j)=d]
再
设
g
(
d
)
为
g
c
d
(
i
,
j
)
为
d
的
倍
数
的
个
数
再设g(d)为gcd(i, j)为d的倍数的个数
再设g(d)为gcd(i,j)为d的倍数的个数
g
(
d
)
=
∑
i
=
1
m
i
n
(
a
/
d
,
b
/
d
)
f
(
d
i
)
g(d) = \sum_{i=1}^{min(a/d, b/d)} f(di)
g(d)=i=1∑min(a/d,b/d)f(di)
同
时
,
根
据
定
义
同时,根据定义
同时,根据定义
g
(
d
)
=
⌊
a
d
⌋
⌊
b
d
⌋
g(d) = \lfloor \frac{a}{d} \rfloor \lfloor \frac{b}{d} \rfloor
g(d)=⌊da⌋⌊db⌋
根
据
莫
比
乌
斯
反
演
的
第
二
种
形
式
,
可
以
从
g
推
出
f
根据莫比乌斯反演的第二种形式,可以从g推出f
根据莫比乌斯反演的第二种形式,可以从g推出f
f
(
d
)
=
∑
i
=
1
m
i
n
(
a
/
d
,
b
/
d
)
μ
(
i
)
g
(
d
i
)
f(d) = \sum_{i=1}^{min(a/d, b/d)} \mu(i) g(di)
f(d)=i=1∑min(a/d,b/d)μ(i)g(di)
设
a
<
b
,
整
理
式
子
得
到
设a < b, 整理式子得到
设a<b,整理式子得到
f
(
d
)
=
∑
i
=
1
a
/
d
∗
μ
(
i
)
⋅
⌊
a
d
i
⌋
⌊
b
d
i
⌋
f(d) =\boxed{ \sum_{i=1}^{a/d} * \mu(i) \cdot \lfloor \frac{a}{di} \rfloor \lfloor \frac{b}{di} \rfloor }
f(d)=i=1∑a/d∗μ(i)⋅⌊dia⌋⌊dib⌋
用 i 替 换 为 k 后 , 和 上 面 的 式 子 是 相 同 的 用i替换为k后,和上面的式子是相同的 用i替换为k后,和上面的式子是相同的
代 码 \large代码 代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 50020;
int n, mu[N+50], p[N+50];
LL sum[N+50];
int tot;
bool used[N+50];
//预处理出素数 莫比乌斯函数
void init() {
mu[1] = 1;
for (int i = 2; i <= N; i++) {
if (!used[i]) {
mu[i] = -1;
p[++tot] = i;
}
for (int j = 1; j <= tot && p[j] * i <= N; j++) {
used[p[j] * i] = true;
if (i % p[j] == 0) {
mu[i * p[j]] = 0;
break;
}
mu[i * p[j]] = mu[i] * (-1);
}
}
for (int i = 1; i <= N; i++) sum[i] = mu[i] + sum[i - 1];
}
LL cal(int a, int b, int d) {
if (a > b) swap(a, b);
a /= d;
b /= d;
LL ans = 0;
//暴力计算 会TLE
// for (int i = 1; i <= a; i++) {
// ans += 1LL * mu[i] * (a / i) * (b / i);
// }
//整除分块
for (int i = 1, j; i <= a; i = j + 1) {
//这里是两个整除分块,取最小值,可以拿(n = 10, m = 20 从i = 6开始想一下)
j = min(a / (a / i), b / (b / i));
ans += 1LL * (sum[j] - sum[i - 1]) * (a / i) * (b / i);
}
return ans;
}
int main() {
int T, a, b, d;
scanf("%d", &T);
init();
while (T--) {
scanf("%d%d%d", &a, &b, &d);
printf("%lld\n", cal(a, b, d));
}
return 0;
}