题解 P2522 【[HAOI2011]Problem b】

kradcigam

2020-04-26 21:32:46

Solution

$$\sum\limits_{i=a}^{b} \sum\limits_{j=c}^{d} [\gcd(i,j)=k]$$ 设 函数 $f(x,y)$ 为: $$\sum\limits_{i=1}^{x} \sum\limits_{j=1}^{y} [\gcd(i,j)=k]$$ 那么,运用容斥原理,原式就 $= f(b,d) - f(a,d) - f(b,c) + f(a,c)$ 所以现在问题就转换为了求 $f$ 函数。 $$\begin{aligned}&\sum\limits_{i=1}^{x} \sum\limits_{j=1}^{y} [\gcd(i,j)=k] \\=& \sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}[\gcd(i,j)=1]\\=& \sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}\varepsilon(\gcd(i,j))\\=& \sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}\sum_{d \mid \gcd(i,j) }\mu(d)\\=& \sum_{d=1 }\mu(d)\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}[d \mid i]\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}[d \mid j]\\=&\sum_{d=1}\mu(d)\lfloor\frac{n}{kd}\rfloor\lfloor\frac{m}{kd}\rfloor\end{aligned}$$ 我们可以使用数论分块进行求解 代码: ```cpp #include <bits/stdc++.h> using namespace std; typedef long long ll; template<typename T>inline void read(T &FF){ T RR=1;FF=0;char CH=getchar(); for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1; for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48); FF*=RR; } const int N=50010; int prim[N],mu[N],sum[N],cnt,k,T; bool vis[N]; void init(){ mu[1]=1; for(register int i=2;i<N;i++){ if(!vis[i]){ mu[i]=-1; prim[++cnt]=i; } for(register int j=1;j<=cnt&&i*prim[j]<N;j++){ vis[i*prim[j]]=1; if(i%prim[j]==0)break; mu[i*prim[j]]=-mu[i]; } } for(register int i=1;i<N;i++)sum[i]=sum[i-1]+mu[i]; }//莫比乌斯反演的板子 ll calc(int a,int b){ ll ans=0; for(register int l=1,r;l<=min(a,b);l=r+1){ r=min(a/(a/l),b/(b/l)); ans+=(1ll*a/l)*(1ll*b/l)*(sum[r]-sum[l-1]); } return ans; } int main(){ init(); for(read(T);T--;){ int a,b,c,d; read(a);read(b);read(c);read(d);read(k); a--;c--;a/=k;b/=k;c/=k;d/=k; printf("%lld\n",calc(b,d)-calc(b,c)-calc(a,d)+calc(a,c)); } return 0; } ```