最小公倍数之和 题解
转化下题面。
求
n∑i=1n∑j=1lcm(i,j)∗cnti∗cntj
其中, n 、 cntk(1≤k≤n) 已事先给出规模均为 5e4 。
n∑i=1n∑j=1lcm(i,j)∗cnti∗cntj
=n∑i=1n∑j=1i∗jgcd(i,j)∗cnti∗cntj
=n∑d=1n∑i=1n∑j=1[gcd(i,j)==d]∗i∗jd∗cnti∗cntj
=n∑d=1⌊nd⌋∑i=1⌊nd⌋∑j=1[gcd(i,j)==1]∗i∗j∗d∗cntid∗cntjd
=n∑d=1⌊nd⌋∑i=1⌊nd⌋∑j=1∑s|gcd(i,j)μ(s)∗i∗j∗d∗cntid∗cntjd
=n∑d=1d∗⌊nd⌋∑i=1⌊nd⌋∑j=1∑s|gcd(i,j)μ(s)∗i∗j∗cntid∗cntjd
=n∑d=1d∗⌊nd⌋∑s=1μ(s)⌊nsd⌋∑i=1⌊nsd⌋∑j=1s2∗i∗j∗cntids∗cntjds
=n∑d=1d∗⌊nd⌋∑s=1μ(s)∗s2⌊nsd⌋∑i=1⌊nsd⌋∑j=1i∗j∗cntids∗cntjds
=n∑d=1d∗⌊nd⌋∑s=1μ(s)∗s2⌊nsd⌋∑i=1i∗cntids⌊nsd⌋∑j=1j∗cntjds
=n∑d=1d∗⌊nd⌋∑s=1μ(s)∗s2(⌊nsd⌋∑i=1i∗cntids)2
=n∑sd=1sd∑s|sd(μ(s)∗s)(⌊nsd⌋∑i=1i∗cntids)2
把 sd 换成 一个漂亮点的数 T , 最后的式子就是
n∑T=1T∗(∑s|Tμ(s)∗s)∗(⌊nT⌋∑i=1i∗cntiT)2
中间的括号可以 O(nlogn) 预处理, 后面的括号暴力算的总复杂度是个调和级数, 复杂度也是 O(nlogn)。
luogu数据AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 50005;
#define li long long
int prime[maxn], v[maxn], mu[maxn], m;
li f[maxn];
void euler(int n) {
mu[1] = 1;
for(int i=2; i<=n; ++i) {
if(!v[i]) {
v[prime[++m] = i] = i;
mu[i] = -1;
}
for(int j=1; j<=m; ++j) {
if(prime[j] > n/i || prime[j] > v[i]) break;
v[prime[j] * i] = prime[j];
mu[prime[j] * i] = mu[i] * (i%prime[j] ? -1 : 0);
}
}
for(int i=1; i<=n; ++i)
for(int j=1; j<=n/i; ++j)
f[i*j] += i * mu[i];
}
int n, a[maxn], c[maxn];
int N;
int main()
{
scanf("%d", &n);
for(int i=1;i<=n;++i) {
scanf("%d", &a[i]);
++c[a[i]];
N = max(N, a[i]);
}
euler(N);
li ans = 0ll;
for(int T=1; T<=N; ++T) {
li nowans = 0ll;
for(int i=1; i<=N/T; ++i) nowans += i*c[i*T];
nowans = nowans * nowans;
ans += T * f[T] * nowans;
}
cout << ans;
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步