旧试题
Link
反演的过程我就简略写写了。
\(\sum\limits_{i=1}^A\sum\limits_{j=1}^B\sum\limits_{k=1}^C\sum\limits_{u|i}\sum\limits_{v|j}\sum\limits_{w|k}\epsilon((u,v))\epsilon((u,w))\epsilon((v,w))\)
\(\sum\limits_{i=1}^A\sum\limits_{j=1}^B\sum\limits_{k=1}^C\lfloor\frac Ai\rfloor\lfloor\frac Bj\rfloor\lfloor\frac Ck\rfloor\sum\limits_{u|(i,j)}\mu(u)\sum\limits_{v|(i,k)}\mu(v)\sum\limits_{w|(j,k)}\mu(w)\)
\(\sum\limits_{u=1}^{\min(A,B)}\sum\limits_{j=1}^{\min(A,C)}\sum\limits_{k=1}^{\min(B,C)}\mu(u)\mu(v)\mu(w)\sum\limits_{\operatorname{lcm}(u,v)|i}\lfloor\frac Ai\rfloor\sum\limits_{\operatorname{lcm}(u,w)|j}\lfloor\frac Bj\rfloor\sum\limits_{\operatorname{lcm}(v,w)|k}\lfloor\frac Ck\rfloor\)
显然\(f(x,y\in\{A,B,C\})=\sum\limits_{x|d}\lfloor\frac yd\rfloor\)可以预处理。
\(\sum\limits_{u=1}^{\min(A,B)}\sum\limits_{j=1}^{\min(A,C)}\sum\limits_{k=1}^{\min(B,C)}\mu(u)\mu(v)\mu(w)f(\operatorname{lcm}(u,v),A)f(\operatorname{lcm}(u,w),B)f(\operatorname{lcm}(v,w),C)\)
观察到\(x>y\Rightarrow f(x,y)=0\),记\(n=\max(A,B,C)\),那么我们可以建一张无向图\(G=([n],\{(u,v)|\mu(u)\ne0\wedge\mu(v)\ne0\wedge\operatorname{lcm}(u,v)\le n\})\),显然对答案有贡献的\((u,v,w)\)在图中构成一个三元环(注意自环)。
建边可以枚举\(k=\operatorname{lcm}(u,v)\)。
打表发现\(n=100000\)时\(|E|=760741\),那么用\(O(|E|^{1.5})\)的三元环计数就行了。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define N 100007
#define P 1000000007
int read(){int x;scanf("%d",&x);return x;}
int gcd(int n,int m){return !m? n:gcd(m,n%m);}
int n,tot,pr[N>>3],mu[N],deg[N],flg[N];
LL fa[N],fb[N],fc[N],sa[N],sb[N],sc[N];
vector<pair<int,int> >G[N];
struct edge{int u,v,w;int cmp(){return deg[u]<deg[v]||(deg[u]==deg[v]&&u<v);}}e[N<<4];
void add(int u,int v,int w){G[u].push_back(make_pair(v,w));}
void Init()
{
flg[1]=mu[1]=1;
for(int i=2,j;i<=100000;++i)
{
if(!flg[i]) pr[++tot]=i,mu[i]=-1;
for(j=1;pr[j]*i<=100000&&j<=tot;++j)
{
flg[i*pr[j]]=1;
if(!(i%pr[j])) {mu[i*pr[j]]=0;break;}
mu[i*pr[j]]=-mu[i];
}
}
}
int main()
{
Init();
int n,m,T=read(),a,b,c,i,j,k,u,v,w,w1,w2,t;
LL ans;
for(;T;--T)
{
a=read(),b=read(),c=read(),n=max(a,max(b,c)),m=ans=0;
for(i=1;i<=n;++i) for(j=i;j<=n;j+=i) fa[i]+=a/j,fb[i]+=b/j,fc[i]+=c/j;
for(i=1;i<=n;++i) ans+=mu[i]*mu[i]*mu[i]*fa[i]*fb[i]*fc[i];
for(i=1;i<=n;++i)
for(j=1;j*i<=n;++j)
{
if(!mu[i*j]) continue;
for(k=1;k*i*j<=n;++k)
{
if(!mu[i*k]||k==j||gcd(j,k)!=1) continue;
u=i*j,v=i*k,w=i*j*k,t=mu[u]*mu[u]*mu[v],ans+=t*fa[u]*fb[w]*fc[w],ans+=t*fb[u]*fa[w]*fc[w],ans+=t*fc[u]*fb[w]*fa[w];
if(k<j) continue;
++m,e[m]=edge{u,v,w},++deg[u],++deg[v];
}
}
for(i=1;i<=m;++i)if(e[i].cmp()) add(e[i].u,e[i].v,e[i].w);else add(e[i].v,e[i].u,e[i].w);
for(u=1;u<=n;++u)
{
for(i=0;i<G[u].size();++i) v=G[u][i].first,w=G[u][i].second,sa[v]=fa[w],sb[v]=fb[w],sc[v]=fc[w];
for(i=0;i<G[u].size();++i)
for(v=G[u][i].first,w1=G[u][i].second,j=0;j<G[v].size();++j)
{
w=G[v][j].first,w2=G[v][j].second,t=mu[u]*mu[v]*mu[w];
ans+=t*fa[w1]*fb[w2]*sc[w];
ans+=t*fb[w1]*fa[w2]*sc[w];
ans+=t*fa[w1]*fc[w2]*sb[w];
ans+=t*fc[w1]*fa[w2]*sb[w];
ans+=t*fb[w1]*fc[w2]*sa[w];
ans+=t*fc[w1]*fb[w2]*sa[w];
}
for(i=0;i<G[u].size();++i) v=G[u][i].first,sa[v]=sb[v]=sc[v]=0;
}
for(i=1;i<=n;++i) fa[i]=fb[i]=fc[i]=deg[i]=0,G[i].clear();
printf("%d\n",ans%P);
}
}