[bzoj2301] [HAOI2011]Problem b
题意:t组数据,求$a\leqslant x \leqslant b , c\leqslant y\leqslant d , gcd(x,y)=k$的个数 $t,a,b,c,d,k \leqslant 50000$
题解:我们可以同时除以k,然后容斥原理,题意转换为求$1\leqslant x \leqslant a1 , 1\leqslant y\leqslant 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} \rfloor*\lfloor \frac{b1}{d} \rfloor$
然后$\lfloor \frac{a1}{d} \rfloor$只有$\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\n",calc(b,d,k)-calc(a-1,d,k)-calc(b,c-1,k)+calc(a-1,c-1,k)); } return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream