题意:
给出(a,b,d),求满足(1 leq x leq a,1 leq y leq b),且(gcd(x,y)=d)的二元组((x,y))的数量。
(1 leq n leq 5 imes 10^4)
(1 leq d leq a,b leq 5 imes 10^4)
题解:
写出式子:
(sum_{i=1}^asum_{j=1}^b[gcd(i,j)=k])
可以把(d)提取出来,变成
(sum_{i=1}^{a/k}sum_{i=1}^{b/k}[gcd(i,j)=1])
可以把(gcd(i,j)=1)变成(sum_{d|gcd(i,j)}mu(d))(莫比乌斯函数的性质),变成
(sum_{i=1}^{a/k}sum_{j=1}^{b/k}sum_{d|gcd(i,j)}mu(d))
即(i,j)都是(d)的倍数,且(d)的范围一定是(min(a,b))。
这里默认(a)是较小的那个,
所以可以把(d)移到前面,变成
(sum_{d=1}^amu(d)[n/kd][m/kd])
然后套一个二维的数论分块,时间复杂度(O(sqrt{n}))。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
typedef long long ll;
int vis[maxn];
ll pri[maxn],mu[maxn],sum[maxn],cnt;
void getMu (ll n) {
//线性筛莫比乌斯函数,并求解前缀和
mu[1]=1;
for (ll i=2;i<=n;i++) {
if (!vis[i]) {
mu[i]=-1;
pri[++cnt]=i;
}
for (ll j=1;j<=cnt&&i*pri[j]<=n;j++) {
vis[i*pri[j]]=1;
if (i%pri[j]==0) break;
else mu[i*pri[j]]=-mu[i];
}
}
for (ll i=1;i<=n;i++) sum[i]=sum[i-1]+mu[i];
}
int main () {
int _;
scanf("%d",&_);
getMu(60000);
while (_--) {
ll A,B,D;
scanf("%lld%lld%lld",&A,&B,&D);
if (A>B) swap(A,B);
ll ans=0;
for (ll l=1,r;l<=A;l=r+1) {
r=min(A/(A/l),B/(B/l));
ans+=(A/(l*D))*(B/(l*D))*(sum[r]-sum[l-1]);
}
printf("%lld
",ans);
}
}