http://www.elijahqi.win/archives/3492
题目地址https://loj.ac/problem/2565
https://www.lydsy.com/JudgeOnline/problem.php?id=5332
首先知道结论
原题所求可以转化为
针对每个gcd莫比乌斯反演
后面这个带下去整符号的东西我们可以考虑n log(n)预处理 设
那么因为后面的东西是
所以直接给他换成lcm的倍数即可
然后考虑这直接暴力是n^3但是显然当f函数的i>n的时候是0 所以我们考虑如何求解
首先把i,j,k都相同的枚举 算答案再算两两相同的答案 n=max(A,B,C);
设点x,y 只有当他们的lcm< n的时候把他们加入然后给无向图定向 使得点度小的往大的连如果相同编号小->大
这样保证每个点出度是sqrt(n)
然后最后再去暴力枚举三元环即可 因为顺序问题 分六种情况讨论
前面的枚举两两相同的采取枚举lcm的方式可以使得复杂度是
#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;
}