题目描述
题解
看到这道题有没有想到sdoi的约数个数和?
没错真的是类似的
首先考虑
d(a∗b∗c)
是多少
有一个结论:
d(a∗b∗c)=∑i|a∑j|b∑k|c[(i,j)=1][(j,k)=1][(i,k)=1]
然后将这个式子带入
∑i=1a∑j=1b∑k=1c∑x|a∑y|b∑z|c[(x,y)=1][(y,z)=1][(x,z)=1]
=∑i=1a∑j=1b∑k=1c⌊ai⌋⌊bj⌋⌊ck⌋[(i,j)=1][(j,k)=1][(i,k)=1]
然后利用反演公式 [n=1]=∑d|nμ(d) 将一个等式化开
=∑i=1a∑j=1b∑k=1c⌊ai⌋⌊bj⌋⌊ck⌋∑d|(i,j)μ(d)[(j,k)=1][(i,k)=1]
=∑k=1c⌊ck⌋∑d=1nμ(d)∑i=1a[d|i]⌊ai⌋[(i,k)=1]∑j=1b[d|j]⌊bj⌋[(j,k)=1]
令 i=di,j=dj
=∑k=1c⌊ck⌋∑d=1nμ(d)∑i=1ad⌊adi⌋[(i,k)=1]∑j=1bd⌊bdj⌋[(j,k)=1]
令 f(n,m)=∑i=1n⌊ni⌋[(i,m)=1]
那么原式
=∑k=1c⌊ck⌋∑d=1aμ(d)f(ad,k)f(bd,k)
求 f 是
优化常数的方法:gcd预处理/记忆化;因为abc的顺序是一定的无所谓的所以选两个小的枚举
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 2005
#define Mod 1073741824
int a,b,c,ans;
int p[N],prime[N],mu[N],G[N][N];
void get(int n)
{
mu[1]=1;
for (int i=2;i<=n;++i)
{
if (!p[i])
{
prime[++prime[0]]=i;
mu[i]=-1;
}
for (int j=1;j<=prime[0]&&i*prime[j]<=n;++j)
{
p[i*prime[j]]=1;
if (i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
else mu[i*prime[j]]=-mu[i];
}
}
}
void Min(int &a,int &b,int &c)
{
if (a>b) swap(a,b);
if (b>c) swap(b,c);
if (a>b) swap(a,b);
}
int gcd(int a,int b)
{
if (!b) return a;
else return gcd(b,a%b);
}
int F(int n,int m)
{
int ans=0;
for (int i=1;i<=n;++i)
if (G[i][m]==1)
ans+=n/i;
return ans;
}
int main()
{
get(2000);
scanf("%d%d%d",&a,&b,&c);
Min(a,b,c);
for (int i=1;i<=c;++i)
for (int j=i;j<=c;++j)
G[i][j]=G[j][i]=gcd(i,j);
for (int i=1;i<=a;++i)
for (int j=1;j<=min(b,c);++j)
if (G[i][j]==1)
ans+=mu[j]*(a/i)*F(b/j,i)*F(c/j,i);
ans=(ans%Mod+Mod)%Mod;
printf("%d\n",ans);
}