求 ∑x=1A∑y=1B∑z=1Cd(xyz) ∑ x = 1 A ∑ y = 1 B ∑ z = 1 C d ( x y z )
类似这道题的结论,我们有
d(xyz)=∑i|x∑j|y∑k|z[(i,j)==1][(j,k)==1][(i,k)==1] d ( x y z ) = ∑ i | x ∑ j | y ∑ k | z [ ( i , j ) == 1 ] [ ( j , k ) == 1 ] [ ( i , k ) == 1 ]
于是带进去,就是求
莫比乌斯反演一下就是:
比如去掉自环,把非三个不同点构成的三元环在外面枚举了。
比如ans最后再取模,不会爆ll。
比如给边定向,把无向图变成有向图。(度数小的向度数大的连边,这样才可以保证复杂度 O(mm−−√) O ( m m ) )
这样的话一个三元环只会被枚举到一次,即你枚举了无序三元组,你需要把六种情况全都统计了。
然后你枚举一个点x,再枚举一个它的出点y,再枚举一个出点z就好啦。
复杂度大概 O(∑(nlog2n)1.5) O ( ∑ ( n l o g 2 n ) 1.5 )
#include
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
#define mod 1000000007
#define pa pair
inline char gc(){
static char buf[1<<16],*S,*T;
if(T==S){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,prime[N>>3],tot=0,mu[N],m,du[N];
ll fa[N],fb[N],fc[N],sa[N],sb[N],sc[N],ans=0;
bool notprime[N];
struct E{
int u,v,w;
bool cmp(){return du[u]20];
vector eg[N];
inline void add(int x,int y,int w){eg[x].push_back(make_pair(y,w));}
inline int gcd(int x,int y){return y?gcd(y,x%y):x;}
inline void init(){
notprime[1]=1;mu[1]=1;
for(int i=2;i<=1e5;++i){
if(!notprime[i]) prime[++tot]=i,mu[i]=-1;
for(int j=1;prime[j]*i<=1e5;++j){
notprime[prime[j]*i]=1;
if(i%prime[j]==0){
mu[prime[j]*i]=0;break;
}mu[prime[j]*i]=-mu[i];
}
}
}
int main(){
// freopen("a.in","r",stdin);
int tst=read();init();
while(tst--){
int A=read(),B=read(),C=read();n=max(A,max(B,C));m=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) ans+=mu[i]*mu[i]*mu[i]*fa[i]*fb[i]*fc[i];
for(int i=1;i<=n;++i)
for(int j=1;i*j<=n;++j){
if(!mu[i*j]) continue;
for(int k=1;i*j*k<=n;++k){
if(!mu[i*k]||k==j||gcd(j,k)!=1) continue;
int u=i*j,v=i*k,w=i*j*k,tmp=mu[u]*mu[u]*mu[v];
ans+=tmp*fa[u]*fb[w]*fc[w];
ans+=tmp*fb[u]*fa[w]*fc[w];
ans+=tmp*fc[u]*fa[w]*fb[w];
if(kcontinue;e[++m].u=u;e[m].v=v;e[m].w=w;
du[u]++;du[v]++;
}
}
for(int 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(int x=1;x<=n;++x){
for(int i=0;iint y=eg[x][i].first,w=eg[x][i].second;
sa[y]=fa[w];sb[y]=fb[w];sc[y]=fc[w];
}for(int i=0;iint y=eg[x][i].first,w1=eg[x][i].second;
for(int j=0;jint z=eg[y][j].first,w2=eg[y][j].second;
int tmp=mu[x]*mu[y]*mu[z];
ans+=tmp*fa[w1]*fb[w2]*sc[z];
ans+=tmp*fa[w1]*sb[z]*fc[w2];
ans+=tmp*fa[w2]*fb[w1]*sc[z];
ans+=tmp*fa[w2]*sb[z]*fc[w1];
ans+=tmp*sa[z]*fb[w1]*fc[w2];
ans+=tmp*sa[z]*fb[w2]*fc[w1];
}
}for(int i=0;iint y=eg[x][i].first,w=eg[x][i].second;
sa[y]=sb[y]=sc[y]=0;
}
}printf("%lld\n",ans%mod);
for(int i=1;i<=n;++i) fa[i]=fb[i]=fc[i]=0,eg[i].clear(),du[i]=0;
}return 0;
}