[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=1∑nj=1∑nlcm(i,j)×ai×aji=1∑nj=1∑ngcd(i,j)i×j×ai×ajd=1∑ni=1∑⌊n/d⌋j=1∑⌊n/d⌋[gcd(i,j)=1]d×i×j×aid×ajd(枚举d=gcd)d=1∑ni=1∑⌊n/d⌋j=1∑⌊n/d⌋k∣gcd(i,j)∑μ(k)×d×i×j×aid×ajdd=1∑nk=1∑⌊n/d⌋i=1∑⌊n/kd⌋j=1∑⌊n/kd⌋μ(k)×d×ik×jk×aidk×ajdkT=1∑nT×(i=1∑⌊n/T⌋i×aiT)2k∣T∑μ(k)×k(设T=kd,k∗k∗d=T∗k)
显
然
∑
k
∣
T
μ
(
k
)
×
k
是
可
以
预
处
理
的
\large 显然\sum_{k|T}\mu(k)\times k是可以预处理的
显然∑k∣Tμ(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;
}