http://www.elijahqi.win/archives/3492
题目地址https://loj.ac/problem/2565
https://www.lydsy.com/JudgeOnline/problem.php?id=5332
首先知道结论
原题所求可以转化为
∑i=1A∑j=1B∑k=1C∑x|i∑y|j∑z|k[gcd(x,y)=1][gcd(x,z)=1][gcd(y,z)=1]
∑
i
=
1
A
∑
j
=
1
B
∑
k
=
1
C
∑
x
|
i
∑
y
|
j
∑
z
|
k
[
g
c
d
(
x
,
y
)
=
1
]
[
g
c
d
(
x
,
z
)
=
1
]
[
g
c
d
(
y
,
z
)
=
1
]
∑x=1A∑y=1B∑z=1C[gcd(x,y)=1][gcd(x,z)=1][gcd(y,z)=1]⌊Ax⌋⌊By⌋⌊Cz⌋
∑
x
=
1
A
∑
y
=
1
B
∑
z
=
1
C
[
g
c
d
(
x
,
y
)
=
1
]
[
g
c
d
(
x
,
z
)
=
1
]
[
g
c
d
(
y
,
z
)
=
1
]
⌊
A
x
⌋
⌊
B
y
⌋
⌊
C
z
⌋
针对每个gcd莫比乌斯反演
∑x=1A∑y=1B∑z=1C∑i|x,i|yμ(i)∑j|x,j|zμ(j)∑k|y,k|zμ(k)⌊Ax⌋⌊By⌋⌊Cz⌋
∑
x
=
1
A
∑
y
=
1
B
∑
z
=
1
C
∑
i
|
x
,
i
|
y
μ
(
i
)
∑
j
|
x
,
j
|
z
μ
(
j
)
∑
k
|
y
,
k
|
z
μ
(
k
)
⌊
A
x
⌋
⌊
B
y
⌋
⌊
C
z
⌋
∑i=1A∑j=1B∑k=1Cμ(i)μ(j)μ(k)∑i|x,j|x⌊Ax⌋∑i|y,k|y⌊By⌋∑j|z,k|z⌊Cz⌋
∑
i
=
1
A
∑
j
=
1
B
∑
k
=
1
C
μ
(
i
)
μ
(
j
)
μ
(
k
)
∑
i
|
x
,
j
|
x
⌊
A
x
⌋
∑
i
|
y
,
k
|
y
⌊
B
y
⌋
∑
j
|
z
,
k
|
z
⌊
C
z
⌋
后面这个带下去整符号的东西我们可以考虑n log(n)预处理 设
fn(i)=∑i|dnnd
f
n
(
i
)
=
∑
i
|
d
n
n
d
那么因为后面的东西是
i|x,j|x
i
|
x
,
j
|
x
所以直接给他换成lcm的倍数即可
然后考虑这直接暴力是n^3但是显然当f函数的i>n的时候是0 所以我们考虑如何求解
首先把i,j,k都相同的枚举 算答案再算两两相同的答案 n=max(A,B,C);
设点x,y 只有当他们的lcm< n的时候把他们加入然后给无向图定向 使得点度小的往大的连如果相同编号小->大
这样保证每个点出度是sqrt(n)
然后最后再去暴力枚举三元环即可 因为顺序问题 分六种情况讨论
前面的枚举两两相同的采取枚举lcm的方式可以使得复杂度是
n∗log(n)2
n
∗
l
o
g
(
n
)
2
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
#define fi first
#define se second
#define ll long long
#define pa pair<int,int>
#define mp(x,y) make_pair(x,y)
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
return x*f;
}
const int N=1e5+10;
const int mod=1e9+7;
inline int gcd(int x,int y){return !y?x:gcd(y,x%y);}
ll ans,fa[N],fb[N],fc[N];bool not_prime[N];vector<pa> eg[N];
int T,prime[N],tot,mu[N],A,B,C,n,sa[N],sb[N],sc[N],d[N];
inline void init(){
mu[1]=1;
for (int i=2;i<=1e5;++i){
if (!not_prime[i]) prime[++tot]=i,mu[i]=-1;
for (int j=1;prime[j]*i<=1e5;++j){
not_prime[prime[j]*i]=1;
if (i%prime[j]==0){
mu[prime[j]*i]=0;break;
}else mu[prime[j]*i]=-mu[i];
}
}
}
struct node{
int x,y,z;
}data[N*10];
inline void insert1(int x,int y,int z){eg[x].push_back(mp(y,z));}
inline bool check(int i){
int x=data[i].x,y=data[i].y;
return d[x]==d[y]?x<y:d[x]<d[y];
}
int main(){
freopen("bzoj5332.in","r",stdin);
T=read();init();
while(T--){
A=read();B=read();C=read();n=max(A,max(B,C));tot=0;ans=0;
for (int i=1;i<=n;++i)
for (int j=i;j<=n;j+=i) fa[i]+=A/j,fb[i]+=B/j,fc[i]+=C/j;
for (int i=1;i<=n;++i) if(mu[i]) ans+=mu[i]*mu[i]*mu[i]*fa[i]*fb[i]*fc[i];
for (int i=1;i<=n;++i){
for (int j=1;j*i<=n;++j){
if (!mu[i*j]) continue;
for (int k=1;k*i*j<=n;++k){
if(k==j||gcd(k,j)!=1||!mu[i*k]) continue;
int x=i*j,y=i*k,z=i*j*k,tmp=mu[x]*mu[x]*mu[y];
ans+=tmp*fa[x]*fb[z]*fc[z];
ans+=tmp*fb[x]*fa[z]*fc[z];
ans+=tmp*fc[x]*fa[z]*fb[z];
if(j>k) continue;data[++tot]=(node){x,y,z};++d[x];++d[y];
}
}
}
for (int i=1;i<=tot;++i) if (check(i)) insert1(data[i].x,data[i].y,data[i].z);
else insert1(data[i].y,data[i].x,data[i].z);
for (int i=1;i<=n;++i){
for (int j=0;j<eg[i].size();++j){
int y=eg[i][j].fi,z=eg[i][j].se;
sa[y]=fa[z];sb[y]=fb[z];sc[y]=fc[z];
}
for (int j=0;j<eg[i].size();++j){
int y=eg[i][j].fi,w1=eg[i][j].se;
for (int k=0;k<eg[y].size();++k){
int z=eg[y][k].fi,w2=eg[y][k].se,x=i,tmp=mu[x]*mu[y]*mu[z];
ans+=tmp*fa[w1]*fb[w2]*sc[z];
ans+=tmp*fa[w1]*fc[w2]*sb[z];
ans+=tmp*fb[w1]*fc[w2]*sa[z];
ans+=tmp*fb[w1]*fa[w2]*sc[z];
ans+=tmp*fc[w1]*fb[w2]*sa[z];
ans+=tmp*fc[w1]*fa[w2]*sb[z];
}
}
for (int j=0;j<eg[i].size();++j){
int y=eg[i][j].fi;sa[y]=sb[y]=sc[y]=0;
}
}
printf("%lld\n",ans%mod);
for (int i=1;i<=n;++i) eg[i].clear(),d[i]=fa[i]=fb[i]=fc[i]=0;
}
return 0;
}