题解好像有一些typo,不过问题不大。本题就是经典莫比乌斯反演套路题
关键问题是读入a的时候要把 a a a转化成 f ( a ) f(a) f(a)
题意
定义一种函数 f ( x ) = x 的 奇 数 次 质 因 子 的 乘 积 , 如 果 x 没 有 奇 数 次 质 因 子 , f ( x ) = 1 f(x)=x的奇数次质因子的乘积,如果x没有奇数次质因子,f(x)=1 f(x)=x的奇数次质因子的乘积,如果x没有奇数次质因子,f(x)=1
读入
n
n
n个数
b
i
b_i
bi,求
∑
1
≤
i
<
j
≤
n
f
(
b
i
∗
b
j
)
\sum_{1 \leq i <j \le n}f(b_i*b_j)
∑1≤i<j≤nf(bi∗bj)
n
,
b
i
≤
2
e
5
n,b_i\le2e5
n,bi≤2e5
题解
首先经过观察可以发现,
f ( b i ∗ b j ) = f ( b i ) ∗ f ( b j ) g c d 2 ( f ( b i ) , f ( b j ) ) f(b_i*b_j) = \frac{f(b_i)*f(b_j)}{gcd^2(f(b_i),f(b_j))} f(bi∗bj)=gcd2(f(bi),f(bj))f(bi)∗f(bj)
由于是一个和 g c d gcd gcd有关的求和式子,考虑莫比乌斯反演。
首先枚举
g
c
d
=
d
gcd=d
gcd=d,那么求和式可以变成:
∑
d
=
1
m
x
1
d
2
∑
i
=
1
m
x
t
o
n
[
i
]
∑
j
=
1
m
x
t
o
n
[
j
]
∗
[
g
c
d
(
i
,
j
)
=
=
d
]
\sum_{d=1}^{mx} \frac{1}{d^2} \sum_{i=1}^{mx} ton[i] \sum_{j=1}^{mx}ton[j]*[gcd(i,j)==d]
∑d=1mxd21∑i=1mxton[i]∑j=1mxton[j]∗[gcd(i,j)==d]
这里给出一些定义和转化:
首先读入
b
i
b_i
bi时,将
b
i
b_i
bi转化为
f
(
b
i
)
f(b_i)
f(bi),不然算
g
c
d
gcd
gcd的贡献时不好处理
t
o
n
[
i
]
表
示
f
(
b
j
)
=
i
的
b
j
个
数
ton[i]表示f(b_j) = i的 b_j个数
ton[i]表示f(bj)=i的bj个数
然后就把最后的判别式化成
∑
T
∣
g
c
d
(
i
,
j
)
μ
(
T
)
\sum_{T|gcd(i,j)} \mu(T)
∑T∣gcd(i,j)μ(T)就可以求和了
然后注意处理一下重复被算的部分。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
const int maxn=2e5+5,N=2e5;
int mu[maxn],p[maxn],cnt,vis[maxn],f[maxn],b[maxn],n,mx;
void get(){
mu[1]=1;f[1]=1;
for(int i=2;i<=N;i++){
if(!vis[i]){
p[++cnt]=i;mu[i]=-1;f[i]=i;
}
for(int j=1;j<=cnt && i*p[j]<=N;j++){
vis[i*p[j]]=1;
mu[i*p[j]]=-mu[i];
if(i%p[j]==0){
vis[i*p[j]]=1;
mu[i*p[j]]=0;
}
}
}
f[1]=1;
for(int i=2;i<=N;i++){
if(vis[i]){
//printf("%d\n",i);
int pos=i;
f[i]=1;
for(int j=1;p[j]*p[j]<=pos && j<=cnt;j++){
int tmp=0;
while(pos%p[j]==0){
pos=pos/p[j];
tmp++;
}
if(tmp>0 && (tmp&1)){
f[i]=f[i]*p[j];
}
}
if(pos!=1){
f[i]=f[i]*pos;
}
}
}
}
inline int ksm(int a,int b){
int ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;b>>=1;
}
return ans;
}
int inv[maxn];
inline int am(int a,int b){
return a+b>=mod?a+b-mod:a+b;
}
int val[maxn];
signed main(){
//freopen("E.in","r",stdin);
//freopen("E.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n;
mx=0;get();
for(int i=1;i<=n;i++){
int a;cin>>a;
a=f[a];
mx=max(mx,a);
b[a]++;
}
int ans=0;
int m=n;
n=mx;
inv[1]=1;
for(int i=2;i<=n;i++){
inv[i]=ksm(i,mod-2);
}
for(int i=1;i<=mx;i++){
if(b[i]>1){
ans=am(ans,(b[i]*(b[i]-1)/2)%mod);
}
}
for(int d=1;d<=n;d++){
for(int t=1;t<=n/d;t++){
int tmp=mu[t];
if(tmp==-1)tmp=mod-1;
tmp=tmp*inv[d]%mod*inv[d]%mod;
int sum=0,alfa=0;
for(int i=1;i<=n/(t*d);i++){
int pi=i*t*d;
sum=am(sum,f[pi]*b[pi]%mod);
alfa=am(alfa,f[pi]*b[pi]%mod*f[pi]*b[pi]%mod);
}
sum=sum*sum%mod;
sum=am(sum,mod-alfa);
sum=sum*inv[2]%mod;
ans=am(ans,tmp*sum%mod);
}
}
printf("%lld\n",ans);
return 0;
}