BZOJ 3994. [SDOI2015]约数个数和
求 $$\sum_{i=1}^n\sum_{j=1}^md(ij)$$
$$d(ij)=\sum_{x|i}\sum_{y|j}[(x,y)=1]=\sum_{x|i}\sum_{y|j}\sum_{p|(x,y)}\mu(p)$$
$$=\sum_p \mu(p)\sum_{x|i}[d|x]\sum_{y|j}[d|y]=\sum_{p|i,p|j}\mu(p)d(\frac{i}{p})d(\frac{j}{p})$$
代回原式得
$$\sum_{i=1}^n\sum_{j=1}^m\sum_{p|i,p|j}\mu(p)d(\frac{i}{p})d(\frac{j}{p})=\sum_{p}\mu(p)\sum_{p|i}d(\frac{i}{p})\sum_{p|j}d(\frac{j}{p})$$
$$=\sum_{p}\mu(p)\sum_{i=1}^{\lfloor \frac{n}{p} \rfloor}d(i)\sum_{j=1}^{\lfloor \frac{m}{p} \rfloor}d(j)$$
令 $s(n)=\sum_{i=1}^n d(i)$
原式为$$\sum_{p}\mu(p)s(\lfloor \frac{n}{p} \rfloor)s(\lfloor \frac{m}{p} \rfloor)$$
#include <bits/stdc++.h> const int N = 5e4 + 7; int mu[N], prime[N], prin, d[N], t[N]; bool vis[N]; void init(int n) { mu[1] = d[1] = t[1] = 1; for (int i = 2; i <= n; i++) { if (!vis[i]) { prime[++prin] = i; d[i] = 2; t[i] = 1; mu[i] = -1; } for (int j = 1; j <= prin && i * prime[j] < N; j++) { vis[i * prime[j]] = 1; if (i % prime[j] == 0) { t[i * prime[j]] = t[i] + 1; mu[i * prime[j]] = 0; d[i * prime[j]] = d[i] / (t[i] + 1) * (t[i] + 2); break; } d[i * prime[j]] = d[i] * 2; t[i * prime[j]] = 1; mu[i * prime[j]] = -mu[i]; } } for (int i = 1; i <= n; i++) mu[i] += mu[i - 1], d[i] += d[i - 1]; } #define ll long long ll solve(int n, int m) { ll ans = 0; if (n > m) std::swap(n, m); for (int i = 1, j; i <= n; i = j + 1) { j = std::min(n / (n / i), m / (m / i)); ans += 1LL * (mu[j] - mu[i - 1]) * 1LL * d[n / i] * d[m / i]; } return ans; } int main() { init(N - 1); int T; scanf("%d", &T); while (T--) { int n, m; scanf("%d%d", &n, &m); printf("%lld\n", solve(n, m)); } return 0; }