题意:t组数据,求$aleqslant x leqslant b , cleqslant yleqslant d , gcd(x,y)=k$的个数 $t,a,b,c,d,k leqslant 50000$
题解:我们可以同时除以k,然后容斥原理,题意转换为求$1leqslant x leqslant a1 , 1leqslant yleqslant b1 , gcd(x,y)=1$的个数。
根据$sum_{d|n}mu(d)=[n=1]$,所以转换为求$sum_{1}^{a1}sum_{1}^{b1}sum_{d|a1,d|b1}mu(d)$
从d看待这个式子,得到$sum_{d=1}^{min(a1,b1)}mu(d)*lfloor frac{a1}{d} floor*lfloor frac{b1}{d} floor$
然后$lfloor frac{a1}{d} floor$只有$sqrt(a1)$种取值. 预处理$mu(i)$的前缀和
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<map> #define MAXN 50000 #define ll long long using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } int f[MAXN+5],s[MAXN/5],num=0; bool b[MAXN+5]; ll calc(int a,int b,int c) { int last;ll ans=0;if(a>b)swap(a,b); a/=c;b/=c; for(int i=1;i<=a;i=last+1) { last=min(b/(b/i),a/(a/i)); ans+=1LL*(f[last]-f[i-1])*(a/i)*(b/i); } return ans; } int main() { f[1]=1; for(int i=2;i<=MAXN;i++) { if(!b[i])s[++num]=i,f[i]=-1; for(int j=1;s[j]*i<=MAXN;j++) { b[s[j]*i]=1; if(i%s[j]==0){f[s[j]*i]=0;break;} f[s[j]*i]=-f[i]; } } for(int i=2;i<=MAXN;i++)f[i]+=f[i-1]; for(int T=read();T;T--) { int a=read(),b=read(),c=read(),d=read(),k=read(); printf("%lld ",calc(b,d,k)-calc(a-1,d,k)-calc(b,c-1,k)+calc(a-1,c-1,k)); } return 0; }