P3455 [POI2007]ZAP-Queries
【题意】
给定a,b,d,求满足$1 \leq x \leq a,1 \leq y \leq b,gcd(a,b)=1$的有序对$(x,y)$的数对数
【分析】
推式子,用莫比乌斯反演的嵌入式形式$[n=1]=\sum_{d|n}\mu(d)$
首先看到$gcd(a,b)=d$这个等于d不好求,我们把$x,y$设为$id,jd$
此时$ans=\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{m}{d}}[gcd(i,j)==1]$
然后用莫比乌斯反演
$ans=\sum_{d=1}^{\frac{n}{d}}\mu{(d)}\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{m}{d}}1$
后面两个用一下数论分块即可
【代码】
#include<bits/stdc++.h> using namespace std; #define mp make_pair #define fi first #define se second #define lson now<<1 #define rson now<<1|1 typedef long long ll; const int maxn=5e4+5; int n,a,b,x; int np[maxn],cnt,mu[maxn],p[maxn]; int sum[maxn]; void init() { mu[1]=1; for(int i=2;i<maxn;i++) { if(!np[i]) { mu[i]=-1; p[++cnt]=i; } for(int j=1;p[j]*i<maxn;j++) { np[i*p[j]]=1; if(i%p[j]==0) { mu[i*p[j]]=0; break; } else mu[i*p[j]]=-mu[i]; } } for(int i=1;i<maxn;i++) sum[i]=sum[i-1]+mu[i]; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%d",&n); init(); for(int i=1;i<=n;i++) { scanf("%d%d%d",&a,&b,&x); ll ans=0; a/=x; b/=x; for(int i=1,j;i<=min(a,b);i=j+1) { j=min(a/(a/i),b/(b/i)); ans+=1LL*(sum[j]-sum[i-1])*(a/i)*(b/i); } printf("%lld\n",ans); } return 0; }