P2522 [HAOI2011]Problem b
【题意】
【分析】
首先我们可以简单容斥一下
设$calc(x,y)=\sum_{i=1}^{x}\sum_{j=1}^{y}[gcd(i,j)=1]$
那么$ans=calc(b,d)-calc(a-1,d)-calc(c-1,b)+calc(a-1,c-1)$
然后求$calc(x,y)$的套路就和P3455 [POI2007]ZAP-Queries一致了,就不再赘述了
【代码】
#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,c,d,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]; } ll calc(int x,int y,int k) { ll res=0; x/=k; y/=k; for(int i=1,j;i<=min(x,y);i=j+1) { j=min(x/(x/i),y/(y/i)); res+=1LL*(sum[j]-sum[i-1])*(x/i)*(y/i); } return res; } 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%d%d",&a,&b,&c,&d,&x); ll ans=0; ans=calc(b,d,x)-calc(a-1,d,x)-calc(b,c-1,x)+calc(a-1,c-1,x); printf("%lld\n",ans); } return 0; }