[luogu P3911] 最小公倍数之和

我丢 : https://www.luogu.com.cn/problem/P3911

思路

这题的关键是在 A i A_i Ai的范围这里,说明这题肯定是和值域有关的
涉及到 l c m lcm lcm肯定和 g c d gcd gcd有关,所以应该是要莫比乌斯反演

题解

记 a [ i ] 为 i 出 现 的 次 数 记a[i]为i出现的次数 a[i]i
∑ i = 1 n ∑ j = 1 n l c m ( i , j ) × a i × a j = ∑ i = 1 n ∑ j = 1 n i × j × a i × a j gcd ⁡ ( i , j ) = ∑ d = 1 n ∑ i = 1 ⌊ n / d ⌋ ∑ j = 1 ⌊ n / d ⌋ [ gcd ⁡ ( i , j ) = 1 ] d × i × j × a i d × a j d ( 枚 举 d = g c d ) = ∑ d = 1 n ∑ i = 1 ⌊ n / d ⌋ ∑ j = 1 ⌊ n / d ⌋ ∑ k ∣ gcd ⁡ ( i , j ) μ ( k ) × d × i × j × a i d × a j d = ∑ d = 1 n ∑ k = 1 ⌊ n / d ⌋ ∑ i = 1 ⌊ n / k d ⌋ ∑ j = 1 ⌊ n / k d ⌋ μ ( k ) × d × i k × j k × a i d k × a j d k = ∑ T = 1 n T × ( ∑ i = 1 ⌊ n / T ⌋ i × a i T ) 2 ∑ k ∣ T μ ( k ) × k ( 设 T = k d , k ∗ k ∗ d = T ∗ k ) \begin{aligned} & \sum_{i=1}^n\sum_{j=1}^n lcm(i,j)\times a_i \times a_j\\ =& \sum_{i=1}^n\sum_{j=1}^n \frac{i \times j\times a_i \times a_j}{\gcd(i,j)} \\ =& \sum_{d=1}^n\sum_{i=1}^{\lfloor n/d \rfloor}\sum_{j=1}^{\lfloor n/d \rfloor}[\gcd(i,j)=1]d\times i \times j \times a_{id} \times a_{jd} (枚举d=gcd)\\ =& \sum_{d=1}^n\sum_{i=1}^{\lfloor n/d \rfloor}\sum_{j=1}^{\lfloor n/d \rfloor}\sum_{k|\gcd(i,j)}\mu(k) \times d\times i \times j \times a_{id} \times a_{jd} \\ =& \sum_{d=1}^n\sum_{k=1}^{\lfloor n/d\rfloor}\sum_{i=1}^{\lfloor n/kd\rfloor}\sum_{j=1}^{\lfloor n/kd\rfloor}\mu(k)\times d \times ik \times jk \times a_{idk} \times a_{jdk} \\ =& \sum_{T=1}^{n}T\times(\sum_{i=1}^{\lfloor n/T \rfloor}i\times a_{iT})^2\sum_{k|T}\mu(k)\times k(设T=kd,k*k*d=T*k) \end{aligned} =====i=1nj=1nlcm(i,j)×ai×aji=1nj=1ngcd(i,j)i×j×ai×ajd=1ni=1n/dj=1n/d[gcd(i,j)=1]d×i×j×aid×ajd(d=gcd)d=1ni=1n/dj=1n/dkgcd(i,j)μ(k)×d×i×j×aid×ajdd=1nk=1n/di=1n/kdj=1n/kdμ(k)×d×ik×jk×aidk×ajdkT=1nT×(i=1n/Ti×aiT)2kTμ(k)×k(T=kd,kkd=Tk)

显 然 ∑ k ∣ T μ ( k ) × k 是 可 以 预 处 理 的 \large 显然\sum_{k|T}\mu(k)\times k是可以预处理的 kTμ(k)×k
code:

#include<bits/stdc++.h>
#define N 1000005
#define int long long
using namespace std;
int prime[N], vis[N], mu[N], s[N], sz;
void init() {
	mu[1] = 1;
	for(int i = 2; i < N; i ++) {
		if(!vis[i]) {
			prime[++ sz] = i;
			mu[i] = -1;
		}
		for(int j = 1; j <= sz && prime[j] * i < N; j ++) {
			vis[prime[j] * i] = 1;
			if(i % prime[j] == 0) break;
			else mu[i * prime[j]] = - mu[i];
		}
	}	
	for(int i = 1; i < N; i ++)
		for(int j = i; j < N; j += i)
			s[j] += mu[i] * i;
}
int n, a[N];
signed main() {
	init();
	scanf("%lld", &n);
	for(int i = 1, x = 0; i <= n; i ++) scanf("%lld", &x), a[x] ++;
	int ans = 0;
	for(int T = 1; T < N; T ++) {
		int ha = 0;
		for(int i = 1; i < N / T; i ++) ha += i * a[i * T];
		ans += T * ha * ha * s[T];
	}
	printf("%lld", ans);	
	return 0;
}

posted @ 2020-05-11 15:13  lahlah  阅读(32)  评论(0编辑  收藏  举报