【题解】Luogu-P3911 最小公倍数之和
Description
-
给定整数 \(n\) 和 \(n\) 个整数 \(a_1, a_2, \dots, a_n\),求
\[\sum_{i = 1}^n \sum_{j = 1}^n \operatorname{lcm}(a_i, a_j) \] -
对于 \(100\%\) 的数据,\(1 \le n, a_i \le 5\times 10^4\)。
Solution
直接反演不行,考虑计算贡献。
设 \(\max\{a_1, a_2, \dots, a_n\} = m\)。
观察到值域(即 \(m\))\(\le 5\times 10^4\),开一个数组 \(c_i\) 记录数 \(i\) 的出现次数。
\[\begin{aligned}
\sum_{i = 1}^n \sum_{j = 1}^n \operatorname{lcm}(a_i, a_j)
& = \sum_{i = 1}^m \sum_{j = 1}^m \operatorname{lcm}(i, j) c_i c_j \\
& = \sum_{i = 1}^m \sum_{j = 1}^m \dfrac{ij}{\gcd(i, j)} c_i c_j \\
& = \sum_{i = 1}^m \sum_{j = 1}^m \sum_{d = 1}^m \dfrac{ij}{d} [\gcd(i, j) = d] c_i c_j \\
& = \sum_{d = 1}^m \sum_{i = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} \sum_{j = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} \dfrac{(id)(jd)}{d} [\gcd(i, j) = 1] c_{id} c_{jd} \\
& = \sum_{d = 1}^m \sum_{i = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} \sum_{j = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} ijd\, c_{id}\, c_{jd} \sum_{k\mid \gcd(i, j)} \mu(k) \\
& = \sum_{d = 1}^m d \sum_{k = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} \mu(k) \sum_{i = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} [k\mid i]\, i\, c_{id} \sum_{j = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} [k\mid j]\, j\, c_{jd} \\
& = \sum_{d = 1}^m d \sum_{k = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} \mu(k) \left(\sum_{i = 1}^{\left\lfloor\frac{m}{dk}\right\rfloor} ik\, c_{idk}\right)^2 \\
& = \sum_{d = 1}^m d \sum_{k = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} \mu(k) k^2 \left(\sum_{i = 1}^{\left\lfloor\frac{m}{T}\right\rfloor} i\, c_{iT} \right)^2 \\
& = \sum_{T = 1}^m \left(\sum_{i = 1}^{\left\lfloor\frac{m}{T}\right\rfloor} i\, c_{iT} \right)^2 \sum_{k\mid T} \mu(k) k^2 \left(\dfrac{T}{k} \right) \\
& = \sum_{T = 1}^m T \left(\sum_{i = 1}^{\left\lfloor\frac{m}{T}\right\rfloor} i\, c_{iT} \right)^2 \sum_{k\mid T} \mu(k) k \\
& = \sum_{T = 1}^m T \left(\sum_{i = 1}^{\left\lfloor\frac{m}{T}\right\rfloor} i\, c_{iT} \right)^2 \sum_{k\mid T} \mu(k) k
\end{aligned}
\]
首先 \(\mu\) 的线性筛是 \(\Omicron(m)\) 的。
对于 \(\sum_{k\mid T} \mu(k) k\),用经典套路枚举倍数 \(\Theta\left(\dfrac{m}{1} + \dfrac{m}{2} + \dfrac{m}{3} + \cdots \right) = \Theta(m\ln m)\) 预处理。
\(\sum_{T = 1}^m T \left(\sum_{i = 1}^{\left\lfloor\frac{m}{T}\right\rfloor} i\, c_{iT} \right)^2\) 直接暴力也是 \(\Theta(m\ln m)\) 的。
总时间复杂度为 \(\Theta(m\ln m)\)。还带大常数
Code
// 18 = 9 + 9 = 18.
#include <iostream>
#include <cstdio>
#define Debug(x) cout << #x << "=" << x << endl
#define int long long
using namespace std;
const int MAXN = 5e4 + 5;
const int N = 5e4;
int p[MAXN], mu[MAXN], res[MAXN];
bool vis[MAXN];
void pre()
{
mu[1] = 1;
for (int i = 2; i <= N; i++)
{
if (!vis[i])
{
p[++p[0]] = i;
mu[i] = -1;
}
for (int j = 1; j <= p[0] && i * p[j] <= N; j++)
{
vis[i * p[j]] = true;
if (i % p[j] == 0)
{
mu[i * p[j]] = 0;
break;
}
mu[i * p[j]] = mu[i] * mu[p[j]];
}
}
for (int i = 1; i <= N; i++)
{
for (int j = 1; i * j <= N; j++)
{
res[i * j] += mu[i] * i;
}
}
}
int a[MAXN], c[MAXN];
signed main()
{
pre();
int n, m = 0;
scanf("%lld", &n);
for (int i = 1; i <= n; i++)
{
scanf("%lld", a + i);
m = max(m, a[i]);
c[a[i]]++;
}
int ans = 0;
for (int i = 1; i <= m; i++)
{
int tmp = 0;
for (int j = 1; j <= m / i; j++)
{
tmp += j * c[j * i];
}
ans += i * tmp * tmp * res[i];
}
printf("%lld\n", ans);
return 0;
}