题目链接
题目解法
首先考虑消去
g
c
d
gcd
gcd 的限制
考虑莫比乌斯反演
优先枚举
d
d
d 可得答案为
∑
d
=
1
n
μ
(
d
)
∗
a
n
s
(
d
)
\sum_{d=1}^{n}\mu(d)*ans(d)
∑d=1nμ(d)∗ans(d)
其中
a
n
s
(
d
)
ans(d)
ans(d) 是所有
a
i
a_i
ai 是
d
d
d 的倍数组成的答案
令
a
i
a_i
ai 为
d
d
d 的倍数的所有数的可重集为
S
S
S
考虑
∑
x
∈
A
x
∗
∑
y
∈
B
y
=
∑
x
∈
A
∑
y
∈
B
x
y
\sum_{x\in A}x*\sum_{y\in B}y=\sum_{x\in A}\sum_{y\in B} xy
∑x∈Ax∗∑y∈By=∑x∈A∑y∈Bxy
考虑每一对
x
,
y
x,y
x,y 贡献的答案
-
x
x
x 与
y
y
y 是同一个数(这里的同一个数不是数值相同)
答案为 x 2 ∗ ( ∣ S ∣ − 1 ) ∗ 2 ∣ S ∣ − 2 x^2*(|S|-1)*2^{|S|-2} x2∗(∣S∣−1)∗2∣S∣−2
对于唯一不在 A A A 中,却在 B B B 中的数有 ∣ S ∣ − 1 |S|-1 ∣S∣−1 中选择,其他 ∣ S ∣ − 2 |S|-2 ∣S∣−2 可选可不选 -
x
x
x 与
y
y
y 不是同一个数(可能数值相同)
答案为 x y ∗ ( ( ∣ S ∣ − 2 ) ∗ 2 ∣ S ∣ − 3 + 2 ∣ S ∣ − 2 ) xy*((|S|-2)*2^{|S|-3}+2^{|S|-2}) xy∗((∣S∣−2)∗2∣S∣−3+2∣S∣−2)
若 x x x 不是唯一 … 的数,那么唯一 … 的数有 ∣ S ∣ − 2 |S|-2 ∣S∣−2 中选择,其他 ∣ S ∣ − 3 |S|-3 ∣S∣−3 可选可不选
若 x x x 是唯一 … 的数,那么其他 ∣ S ∣ − 2 |S|-2 ∣S∣−2 个数可选可不选
考虑
f
r
e
q
freq
freq 的值域很大,考虑对每个数值共同考虑
分类仍然相同
-
x
x
x 与
y
y
y 是同一个数
A n s = f r e q x ∗ x 2 ∗ ( ∣ S ∣ − 1 ) ∗ 2 ∣ S ∣ − 2 Ans=freq_x*x^2*(|S|-1)*2^{|S|-2} Ans=freqx∗x2∗(∣S∣−1)∗2∣S∣−2 -
x
x
x 与
y
y
y 不是同一个数(可能数值相同)
继续分类讨论
若 x , y x,y x,y 数值相同
A n s = f r e q x ∗ ( f r e q x − 1 ) ∗ x 2 ∗ ( ( ∣ S ∣ − 2 ) ∗ 2 ∣ S ∣ − 3 + 2 ∣ S ∣ − 2 ) Ans=freq_x*(freq_x-1)*x^2*((|S|-2)*2^{|S|-3}+2^{|S|-2}) Ans=freqx∗(freqx−1)∗x2∗((∣S∣−2)∗2∣S∣−3+2∣S∣−2)
若 x , y x,y x,y 数值不同
令 s u m = ∑ d ∣ i i ∗ f r e q i sum=\sum_{d|i} i*freq_i sum=∑d∣ii∗freqi
A n s = f r e q x ∗ x ∗ ( s u m − f r e q x ∗ x ) ∗ ( ( ∣ S ∣ − 2 ) ∗ 2 ∣ S ∣ − 3 + 2 ∣ S ∣ − 2 ) Ans=freq_x*x*(sum-freq_x*x)*((|S|-2)*2^{|S|-3}+2^{|S|-2}) Ans=freqx∗x∗(sum−freqx∗x)∗((∣S∣−2)∗2∣S∣−3+2∣S∣−2)
实际复杂度为调和级数 O ( n l n n ) O(nln\;n) O(nlnn)
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N(100100),P(998244353);
int n,ans,mu[N],sum[N];
int pr[N],cnt;
bool vis[N];
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
int qmi(int a,int b){
if(b<0) return 0;
int res=1;
for(;b;b>>=1){
if(b&1) res=res*a%P;
a=a*a%P;
}
return res;
}
int solve(int d){
int tot1=0,tot2=0;
for(int i=d;i<=100000;i+=d) tot1+=sum[i],tot2=(tot2+sum[i]%P*i%P)%P;
if(tot1<2) return 0;
int pw1=qmi(2,(tot1-3)%(P-1)),pw2=qmi(2,(tot1-2)%(P-1));
tot1%=P;
int res=0;
for(int i=d;i<=100000;i+=d){
int t=sum[i]%P;
//x,y是同一个数
res=(res+t*i%P*i%P*(tot1-1+P)%P*pw2%P)%P;
//x,y的数值相同
if(sum[i]>=2) res=(res+t*(t-1+P)%P*i%P*i%P*((tot1-2+P)*pw1%P+pw2)%P)%P;
//x,y数值不同
res=(res+t*i%P*(tot2-i*t%P+P)%P*((tot1-2+P)*pw1%P+pw2)%P)%P;
}
return res;
}
void sieve(){
mu[1]=1;
for(int i=2;i<=100000;i++){
if(!vis[i]) vis[i]=1,pr[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&pr[j]<=100000/i;j++){
vis[pr[j]*i]=1;
if(i%pr[j]==0) break;
mu[i*pr[j]]=-mu[i];
}
}
}
signed main(){
n=read(),sieve();
for(int i=1,x,y;i<=n;i++) x=read(),y=read(),sum[x]+=y;
for(int i=1;i<=100000;i++) if(mu[i]) ans=((ans+mu[i]*solve(i))%P+P)%P;
printf("%lld",ans);
return 0;
}