题意
设(f(n)=sumlimits_{i=1}^{a}sumlimits_{j=1}^{b}[gcd(i,j)==n],F(n)=sumlimits_{n|d}f(d))
发现(F(n)=frac{a}{n}*frac{b}{n}),可以理解为对(a)以内的所有(k*n)都和(b)以内的(k*n)配对了一次。
由莫比乌斯反演:
(f(n)=sumlimits_{n|d}mu(frac{d}{n})F(d))
(f(n)=sumlimits_{n|d}mu(frac{d}{n})frac{a}{d}*frac{b}{d})
设(t=frac{d}{n})。
(f(n)=sumlimits_{t=1}^{min(frac{a}{d},frac{b}{d})}mu(t)frac{a}{t*n}frac{b}{t*n})
(ans=f(d))
除法分块即可。
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=50010;
int T;
int mu[maxn],sum[maxn];
ll a,b,d;
bool vis[maxn];
vector<int>prime;
inline void shai(int n)
{
vis[1]=1;mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i])prime.push_back(i),mu[i]=-1;
for(unsigned int j=0;j<prime.size()&&i*prime[j]<=n;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0){mu[i*prime[j]]=0;break;}
mu[i*prime[j]]=-mu[i];
}
}
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+mu[i];
}
inline ll solve(ll a,ll b,ll d)
{
ll n=min(a/d,b/d),res=0;
for(int l=1,r;l<=n;l=r+1)
{
r=min(a/(a/l),b/(b/l));
res+=(a/(l*d))*(b/(l*d))*(sum[r]-sum[l-1]);
}
return res;
}
int main()
{
shai(50000);
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld%lld",&a,&b,&d);
printf("%lld
",solve(a,b,d));
}
return 0;
}