题解 P3911 最小公倍数之和

博客详细解析了如何求解对于A1到AN的最小公倍数之和的问题,通过数学推导和利用最小公倍数的定义,结合莫比乌斯函数进行求解,最终给出暴力计算的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

对于 A 1 , A 2 , . . . , A N A_1,A_2,...,A_N A1,A2,...,AN,求:
∑ i = 1 N ∑ j = 1 N l c m ( A i , A j ) \sum_{i=1}^N\sum_{j=1}^Nlcm(A_i,A_j) i=1Nj=1Nlcm(Ai,Aj)
的值
l c m ( a , b ) lcm(a,b) lcm(a,b) 表示a 和b 的最小公倍数

输入输出格式

输入格式

第1行,1个整数N。

第2行,N个整数 A 1 , A 2 , . . . , A N A_1,A_2,...,A_N A1,A2,...,AN

输出格式

1个整数,表示所求的值。

思路讲解

求:
ans = ∑ i = 1 N ∑ j = 1 N [ A i , A j ] \text{ans}=\sum_{i=1}^N\sum_{j=1}^N[A_i,A_j] ans=i=1Nj=1N[Ai,Aj]
考虑到:
1 ≤ A i ≤ 50000 1≤A_i≤50000 1Ai50000
令:
M = max ⁡ 1 ≤ i ≤ N { A i } M=\max_{1\le i\le N}\{A_i\} M=1iNmax{Ai}
C i = ∑ d = 1 M [ A d = i ] C_i=\sum_{d=1}^{M}[A_d=i] Ci=d=1M[Ad=i]
于是:
ans = ∑ i = 1 M ∑ j = 1 M C i ⋅ C j ⋅ [ i , j ] \text{ans}=\sum_{i=1}^M\sum_{j=1}^MC_i\cdot C_j\cdot [i,j] ans=i=1Mj=1MCiCj[i,j]
然后就是愉快地推式子。

根据最小公倍数的定义,我们有:
= ∑ i = 1 M ∑ j = 1 M C i ⋅ C j ⋅ i ⋅ j ( i , j ) =\sum_{i=1}^M\sum_{j=1}^M\frac{C_i\cdot C_j\cdot i\cdot j}{(i,j)} =i=1Mj=1M(i,j)CiCjij
尝试枚举 d = ( i , j ) d=(i,j) d=(i,j)
= ∑ i = 1 M ∑ j = 1 M ∑ d ∣ i ∧ d ∣ j ∧ ( i d , j d ) = 1 C i ⋅ C j ⋅ i ⋅ j d =\sum_{i=1}^M\sum_{j=1}^M\sum_{d|i∧d|j∧(\frac{i}{d},\frac{j}{d})=1}\frac{C_i\cdot C_j\cdot i\cdot j}{d} =i=1Mj=1Mdidj(di,dj)=1dCiCjij
尝试将和式提前:
= ∑ d = 1 M ∑ i = 1 ⌊ M d ⌋ ∑ j = 1 ⌊ M d ⌋ [ ( i , j ) = 1 ] d ⋅ i ⋅ j ⋅ C i d ⋅ C j d =\sum_{d=1}^M\sum_{i=1}^{\left\lfloor\frac{M}{d}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{M}{d}\right\rfloor}[(i,j)=1]d\cdot i\cdot j\cdot C_{id}\cdot C_{jd} =d=1Mi=1dMj=1dM[(i,j)=1]dijCidCjd
引入莫比乌斯函数:
= ∑ d = 1 M ∑ i = 1 ⌊ M d ⌋ ∑ j = 1 ⌊ M d ⌋ ∑ k ∣ ( i , j ) μ ( k ) ⋅ d ⋅ i ⋅ j ⋅ d ⋅ C i d k ⋅ C j d k =\sum_{d=1}^M\sum_{i=1}^{\left\lfloor\frac{M}{d}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{M}{d}\right\rfloor}\sum_{k|(i,j)}μ(k)\cdot d\cdot i\cdot j\cdot d\cdot C_{idk}\cdot C_{jdk} =d=1Mi=1dMj=1dMk(i,j)μ(k)dijdCidkCjdk
再将和式提前:
= ∑ d = 1 n ∑ k = 1 ⌊ M d ⌋ ∑ i = 1 ⌊ M k d ⌋ ∑ j = 1 ⌊ M k d ⌋ k 2 μ ( k ) ⋅ i ⋅ j ⋅ j ⋅ C i d k ⋅ C j d k =\sum_{d=1}^n\sum_{k=1}^{\lfloor\frac{M}{d}\rfloor}\sum_{i=1}^{\lfloor\frac{M}{kd}\rfloor}\sum_{j=1}^{\lfloor\frac{M}{kd}\rfloor}k^2μ(k)\cdot i\cdot j\cdot j\cdot C_{idk}\cdot C_{jdk} =d=1nk=1dMi=1kdMj=1kdMk2μ(k)ijjCidkCjdk
δ = k ⋅ d \delta=k\cdot d δ=kd,简化一层和式:
= ∑ δ = 1 M δ ( ∑ i = 1 ⌊ M δ ⌋ i ⋅ C δ i ) 2 ∑ k ∣ δ k μ ( k ) =\sum_{\delta=1}^M\delta\bigg(\sum_{i=1}^{\lfloor\frac{M}{\delta}\rfloor}i\cdot C_{\delta i}\bigg)^2\sum_{k|\delta}kμ(k) =δ=1Mδ(i=1δMiCδi)2kδkμ(k)
令:
S δ = ∑ k ∣ δ k μ ( k ) S_{\delta}=\sum_{k|\delta}kμ(k) Sδ=kδkμ(k)
可预处理,最后就是个暴力:

#include <cstdio>
#include <iostream>

using namespace std;
const int N = 50001;
typedef long long ll;
int n, m, tot, Mu[N], flag[N], P[N], C[N];
ll s[N], ans;

void sieve() {
	Mu[1] = 1;
	for(int i = 2; i <= n; i++) {
		if(!flag[i]) P[++tot] = i, Mu[i] = -1;
		for(int j = 1; j <= tot; j++) {
			if(i * P[j] > n) break;
			flag[i * P[j]] = 1;
			Mu[i * P[j]] = -Mu[i];
			if(i % P[j] == 0) {Mu[i * P[j]] = 0; break;}
		}
	}
}
int main()
{
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) { int x; scanf("%d", &x); ++C[x]; m = max(m, x);}
	n = m;
	sieve();
	for(int i = 1; i <= n; i++) {
		for(int j = i; j <= n; j += i) {
			s[j] += 1LL * Mu[i] * i;
		}
	}
	for(int T = 1; T <= n; T++) {
		ll res = 0;
		for(int i = 1; i <= n / T; i++) res += 1LL * i * C[i * T];
		ans += T * res * res * s[T];
	}
	printf("%lld", ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值