2021-7-31
这道题使用莫比乌斯反演,比较套路化
P3911
求 ∑ i = 1 n ∑ j = 1 n l c m ( A i , A j ) \sum^{n}_{i=1}\sum^{n}_{j=1}lcm(A_i,A_j) ∑i=1n∑j=1nlcm(Ai,Aj)。
可以发现 A i A_i Ai的值不算特别大,瞬间想到桶(剧透)
我们定义 a i a_i ai为数 i i i的出现次数, m m m为一个值出现最多的次数。
那么开始推式子:
A
n
s
=
∑
i
=
1
m
∑
j
=
1
m
a
i
a
j
×
l
c
m
(
i
,
j
)
Ans=\sum^{m}_{i=1}\sum^{m}_{j=1}a_ia_j\times lcm(i,j)
Ans=i=1∑mj=1∑maiaj×lcm(i,j)
根据小学奥数知识(真就小奥)的
a
×
b
=
g
c
d
(
a
,
b
)
×
l
c
m
(
a
,
b
)
a\times b=gcd(a,b)\times lcm(a,b)
a×b=gcd(a,b)×lcm(a,b)
可得:
A n s = ∑ d = 1 m ∑ i = 1 m ∑ j = 1 m i j a i a j d [ g c d ( i , j ) = d ] Ans=\sum_{d=1}^{m}\sum^{m}_{i=1}\sum^{m}_{j=1}\frac{ija_ia_j}{d}[gcd(i,j)=d] Ans=d=1∑mi=1∑mj=1∑mdijaiaj[gcd(i,j)=d]
A n s = ∑ d = 1 m 1 d ∑ i = 1 m ∑ j = 1 m i j a i a j [ g c d ( i , j ) = d ] Ans=\sum_{d=1}^{m}\frac{1}{d}\sum^{m}_{i=1}\sum^{m}_{j=1}ija_ia_j[gcd(i,j)=d] Ans=d=1∑md1i=1∑mj=1∑mijaiaj[gcd(i,j)=d]
令 f ( x ) = ∑ i = 1 m ∑ j = 1 m i j a i a j [ g c d ( i , j ) = d ] f(x)=\sum^{m}_{i=1}\sum^{m}_{j=1}ija_ia_j[gcd(i,j)=d] f(x)=i=1∑mj=1∑mijaiaj[gcd(i,j)=d]
构造 F ( x ) = ∑ x ∣ d f ( d ) F(x)=\sum_{x|d}f(d) F(x)=x∣d∑f(d)
可得
F
(
x
)
=
∑
i
=
1
m
∑
j
=
1
m
i
j
a
i
a
j
[
x
∣
g
c
d
(
i
,
j
)
]
F(x)=\sum^{m}_{i=1}\sum^{m}_{j=1}ija_ia_j[x|gcd(i,j)]
F(x)=i=1∑mj=1∑mijaiaj[x∣gcd(i,j)]
=
∑
x
∣
i
∑
x
∣
j
i
j
a
i
a
j
=\sum_{x|i}\sum_{x|j}ija_ia_j
=x∣i∑x∣j∑ijaiaj
=
∑
x
∣
i
i
a
i
×
∑
x
∣
j
j
a
j
=\sum_{x|i}ia_i\times \sum_{x|j}j a_j
=x∣i∑iai×x∣j∑jaj
=
(
∑
x
∣
i
i
a
i
)
2
=(\sum_{x|i}ia_i)^2
=(x∣i∑iai)2
由反演可得:
f ( d ) = ∑ x = 1 ⌊ m d ⌋ μ ( x ) F ( d x ) f(d)=\sum_{x=1}^{\lfloor \frac{m}{d}\rfloor} \mu(x) F(dx) f(d)=x=1∑⌊dm⌋μ(x)F(dx)
那么带入 A n s Ans Ans
A
n
s
=
∑
d
=
1
m
1
d
f
(
d
)
Ans=\sum^{m}_{d=1}\frac{1}{d}f(d)
Ans=d=1∑md1f(d)
=
∑
d
=
1
m
1
d
∑
g
=
1
⌊
m
d
⌋
μ
(
g
)
F
(
g
d
)
=\sum^{m}_{d=1}\frac{1}{d}\sum_{g=1}^{\lfloor \frac{m}{d}\rfloor} \mu(g) F(gd)
=d=1∑md1g=1∑⌊dm⌋μ(g)F(gd)
我们可以用 O ( n log n ) O(n \log n) O(nlogn)的时间复杂度求出 F F F,然后用 O ( n log n ) O(n \log n) O(nlogn)的时间复杂度求出该式子
代码:
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
#define int long long
const int Maxn=50010;
int n,Ar[Maxn];
int m,Tong[Maxn];
int f[Maxn],ans;
int ret,prime[Maxn],mu[Maxn];
bool flag[Maxn];
void get_mu()
{
mu[1]=1;
for(int i=2;i<=m;i++)
{
if(!flag[i])
{
prime[++ret]=i;
mu[i]=-1;
}
for(int j=1;j<=ret && prime[j]<=m/i;j++)
{
flag[i*prime[j]]=true;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}else{
mu[i*prime[j]]=-mu[i];
}
}
}
}
signed main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&Ar[i]);
m=max(m,Ar[i]);
Tong[Ar[i]]++;
}
//m=50000;
for(int i=1;i<=m;i++)
{
for(int j=i;j<=m;j+=i)
{
f[i]+=Tong[j]*j;
}
}
for(int i=1;i<=m;i++)
{
f[i]*=f[i];
}
get_mu();
for(int i=1;i<=m;i++)
{
int tot=0;
for(int j=1;j<=m/i;j++)
{
tot+=mu[j]*f[i*j];
}
ans+=tot/i;
}
printf("%lld\n",ans);
return 0;
}
然而还有一道比较相似的题目:
[AGC038C] LCMs
只不过是把问题改为了:
∑ i = 1 n ∑ j = i + 1 n l c m ( A i , A j ) \sum^{n}_{i=1}\sum^{n}_{j=i+1}lcm(A_i,A_j) i=1∑nj=i+1∑nlcm(Ai,Aj)的值模 998244353 998244353 998244353
然而式子也比较像。
双倍经验!!!111
代码:
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int Mod=998244353;
const int inv2=499122177;
#define int long long
const int Maxn=1e6+10;
int n,Ar[Maxn];
int m,Tong[Maxn];
int f[Maxn],ans;
int ret,prime[Maxn],mu[Maxn];
bool flag[Maxn];
void get_mu()
{
mu[1]=1;
for(int i=2;i<=m;i++)
{
if(!flag[i])
{
prime[++ret]=i;
mu[i]=-1;
}
for(int j=1;j<=ret && prime[j]<=m/i;j++)
{
flag[i*prime[j]]=true;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}else{
mu[i*prime[j]]=-mu[i];
}
}
}
}
signed main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&Ar[i]);
m=max(m,Ar[i]);
Tong[Ar[i]]++;
ans-=Ar[i];
}
//m=50000;
get_mu();
for(int i=1;i<=m;i++)
{
for(int j=i;j<=m;j+=i)
{
f[j]=(f[j]+mu[i]*i%Mod);
}
}
for(int i=1;i<=m;i++)
{
int tot=0;
for(int j=1;j<=m/i;j++)
{
tot=(tot+j*Tong[i*j]%Mod)%Mod;
}
ans=(ans+i*f[i]%Mod*tot%Mod*tot%Mod)%Mod;
}
ans=(ans*inv2%Mod+Mod)%Mod;
printf("%lld\n",ans);
return 0;
}
莫比乌斯反演大法好!!!11