题意:
求
∑ax∑by[(a,b)=d]
题解:
sb反演题。
推一波柿子可得
∑kmin(⌊ad⌋,⌊bd⌋)μ(k)⌊adk⌋⌊adk⌋
然后就可以分块了。
code:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#define LL long long
using namespace std;
int prime[50010],pr=0,mu[50010];
bool v[50010];
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f*x;
}
void pre()
{
memset(v,true,sizeof(v));
mu[1]=1;
for(int i=2;i<=50000;i++)
{
if(v[i]) prime[++pr]=i,mu[i]=-1;
for(int j=1;j<=pr&&prime[j]*i<=50000;j++)
{
v[prime[j]*i]=false;
if(i%prime[j]==0) {mu[i*prime[j]]=0;break;}
else mu[i*prime[j]]=-mu[i];
}
}
for(int i=2;i<=50000;i++) mu[i]+=mu[i-1];
}
int main()
{
pre();
int T;T=read();
while(T--)
{
int a,b,d;a=read();b=read();d=read();
a/=d;b/=d;int j;LL ans=0;
for(int i=1;i<=min(a,b);i=j+1)
{
j=min(a/(a/i),b/(b/i));
ans=ans+(mu[j]-mu[i-1])*(LL)(a/i)*(LL)(b/i);
}
printf("%lld\n",ans);
}
}