【题解】Luogu-P3911 最小公倍数之和

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;
}
posted @ 2022-01-19 18:05  mango09  阅读(32)  评论(0编辑  收藏  举报
-->