题解 P2522 【[HAOI2011]Problem b】
对于给出的 \(n\) 个询问,每次求有多少个数对 \((x,y)\),满足 \(a \le x \le b\),\(c \le y \le d\),且 \(\gcd(x,y) = k\),\(\gcd(x,y)\) 函数为 \(x\) 和 \(y\) 的最大公约数。
前置知识
\[\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}
\]
我们可以使用数论分块进行求解
代码:
#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;
}