【题解】【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;
} 
posted @ 2019-12-28 22:02  Refined_heart  阅读(117)  评论(0编辑  收藏  举报