BZOJ 2301 [HAOI2011]Problem b (莫比乌斯反演)
题目大意:已知x\in [a,b],y\in [c,d],求gcd(x,y)为k的有序数对数量 a,b,c,d,k及询问数<=50000
比yy的gcd好做一些吧
转化题目,直接求解比较困难,利用容斥原理,问题转化为求$ans(b,d)-ans(a-1,d)-ans(b,c-1)+ans(a-1,c-1)$
求$\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)==k]$
化简$\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{m}{k} \right \rfloor}[gcd(i,j)==1]$
套路变形$\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\left \lfloor \frac{n}{kd} \right \rfloor \cdot \left \lfloor \frac{m}{kd} \right \rfloor\cdot \mu(d)$
预处理$\mu(d)$的前缀和,再整除分块的思想求解即可
与yy的gcd那道题不同,整除分块的部分有一些细节需要思考
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N 50100 5 #define maxn 50000 6 #define ll long long 7 using namespace std; 8 9 int T,a,b,c,d,K,cnt; 10 int use[N],pr[N],mu[N],pmu[N]; 11 void Pre() 12 { 13 mu[1]=1; 14 for(int i=2;i<=maxn;i++) 15 { 16 if(!use[i]) pr[++cnt]=i,mu[i]=-1; 17 for(int j=1;j<=cnt&&i*pr[j]<=maxn;j++){ 18 use[i*pr[j]]=1; 19 if(i%pr[j]==0){ 20 mu[i*pr[j]]=0; 21 break; 22 }else{ 23 mu[i*pr[j]]=-mu[i]; 24 } 25 } 26 } 27 for(int i=1;i<=maxn;i++) 28 pmu[i]=pmu[i-1]+mu[i]; 29 } 30 ll solve(int n,int m) 31 { 32 if(n>m) swap(n,m); 33 ll ans=0;int nd,md; 34 for(int i=1,la,mi=min(n/K,m/K);i<=mi;i=la+1) 35 { 36 nd=n/K,md=m/K; 37 la=min(nd/(nd/i),md/(md/i)); 38 ans+=1ll*(n/(K*i))*(m/(K*i))*(pmu[la]-pmu[i-1]); 39 }return ans; 40 } 41 int main() 42 { 43 scanf("%d",&T); 44 Pre(); 45 for(int t=1;t<=T;t++) 46 { 47 scanf("%d%d%d%d%d",&a,&b,&c,&d,&K); 48 printf("%lld\n",solve(b,d)-solve(a-1,d)-solve(b,c-1)+solve(a-1,c-1)); 49 } 50 return 0; 51 }