题 意 \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
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;
}
整除分块 ↩︎
莫比乌斯反演 ↩︎