【题解】【HAOI2011】Problem b
\(Luogu2522\)
题目大意:求下面式子的值:
\[\sum_{i=x}^n\sum_{j=y}^m[\gcd(i,j)=k]
\]
这个东西直接求不好求,考虑差分,从\([1,n]\)的范围求,然后相减。
那么考虑:
\[\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=k]
\]
同时除以\(k\):
\[\sum_{i=1}^{\frac{n}{k}}\sum_{j=1}^{\frac{m}{k}}[gcd(i,j)=1]
\]
枚举\(d|gcd(i,j)\),套上反演套路,并且将\(d\)提到前面:
\[\sum_{i=1}^{\frac{n}{k}}\sum_{j=1}^{\frac{m}{k}}\sum_{d|gcd(i,j)}\mu(d)
\]
\[=\sum_{d=1}^{n}\mu(i)\sum_{i=1}^{\frac{n}{kd}}\sum_{j=1}^{\frac{m}{kd}}
\]
\[=\sum_{d=1}^{n}\mu(i)\frac{n}{kd}\frac{m}{kd}
\]
这玩意到此结束,后面数论分块即可,\(O(\sqrt{n})\).
套一个差分即可。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int MAXN=6e4+10;
int n,m;
int prime[MAXN],mu[MAXN];
int fg[MAXN],tot,sum[MAXN];
void screen(){
mu[1]=1;
for(int i=2;i<=MAXN;++i){
if(!fg[i])prime[++tot]=i,mu[i]=-1;
for(int j=1;j<=tot&&i*prime[j]<=MAXN;++j){
fg[i*prime[j]]=1;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
for(int i=1;i<=MAXN;++i)sum[i]=sum[i-1]+mu[i];
}
int solve(int x,int y,int k){
int ans=0,M;
M=min(x,y);
for(int l=1,r;l<=M;l=r+1){
r=min(x/(x/l),y/(y/l));
ans+=(x/(l*k))*(y/(l*k))*(sum[r]-sum[l-1]);
}
return ans;
}
int main(){
scanf("%d",&n);
screen();
for(;n;n--){
int k,a,b,c,d;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
printf("%d\n",solve(b,d,k)-solve(a-1,d,k)-solve(b,c-1,k)+solve(a-1,c-1,k));
}
return 0;
}