GCD3[caioj1282]\[BZOJ2301]莫反

欢迎大家访问我的老师的OJ———caioj.cn

题面描述

caioj

bzoj

注意,caioj题面略有不同

思路

Zap很像。

D(a,b,k)D(a,b,k)表示满足xa,ybx\le a,y\le bkgcd(x,y)k \mid \gcd(x,y)的二元组有多少对。

由于D(a,b,k)=a/kb/kD(a,b,k)=\left\lfloor a/k\right\rfloor* \left\lfloor b/k\right\rfloor

F(a,b)F(a,b)表示满足xa,ybx\le a,y\le b并且x,yx,y互质的二元组有多少对。

由于

F(a,b)=i=1min(a,b)μ(i)D(a,b,i)F(a,b)=\sum_{i=1}^{\operatorname{min}(a,b)}\mu(i)*D(a,b,i)

那么我们现在多了axb,cyda\le x\le b,c\le y\le d这个限制。

F(a,b)F(a,b)的定义下手:满足xa,ybx\le a,y\le b并且x,yx,y互质的二元组有多少对

我们现在要求满足axb,cyda\le x\le b,c\le y\le d并且x,yx,y互质的二元组有多少对

我们转化一下条件:

满足axb,cyda\le x\le b,c\le y\le d并且x,yx,y互质的二元组有多少对\leftrightarrow

满足xb,ydx\le b,y\le dx,yx,y互质,且不满足x<ax<ay<cy<c的二元组有多少对

那么我们就可以得到区间F(b,d),F(a1,c1),F(a1,d),F(b,c1)F(b,d),F(a-1,c-1),F(a-1,d),F(b,c-1)

其中F(a1,d),F(b,c1)F(a-1,d),F(b,c-1)就是分别x<a,y<cx<a,y<c的不符合题意的二元组数量,

根据容斥原理,因为F(a1,d)F(a-1,d)中所包含的二元组与F(b,c1)F(b,c-1)包含的二元组会有交集,交集重复算了两次,要去重

所以我们要相应的加上F(a1,d)F(b,c1)F(a-1,d)\cap F(b,c-1),即F(a1,c1)F(a-1,c-1)

所以答案就为:

F(b,d)+F(a1,c1)F(a1,d)F(b,c1)F(b,d)+F(a-1,c-1)-F(a-1,d)-F(b,c-1)

AC code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#define ll long long
#define gc getchar()
using namespace std;
const int N=1e5+5;
const int inf=1e5;
const int M=5e4+5;
int n,prime[M],m,miu[N];bool v[N];
inline void qr(int &x)
{
	x=0;int f=1;char c=gc;
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
	while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
	x*=f;
}
void g_p()
{
	m=0;memset(v,false,sizeof(v));miu[1]=1;
	for(int i=2;i<=inf;i++)
	{
		if(!v[i])prime[++m]=i,miu[i]=-1;
		for(int j=1;j<=m&&i*prime[j]<=inf;j++)
		{
			v[i*prime[j]]=1;
			if(i%prime[j]==0){miu[i*prime[j]]=0;break;}
			miu[i*prime[j]]=-miu[i];
		}
	}
	for(int i=2;i<=inf;i++)miu[i]+=miu[i-1];
}
ll calc(int a,int b)
{
	if(a>b)swap(a,b);
	ll ans=0;
	for(int x=1,gx;x<=a;x=gx+1)//分块 
	{
		gx=min(a/(a/x),b/(b/x));
		ans+=(ll)(miu[gx]-miu[x-1])*(a/x)*(b/x);
	}
	return ans;
	
}
int main()
{
	g_p();
	int t;qr(t);
	while(t--)
	{
		int a,b,c,d,k;qr(a),qr(b),qr(c),qr(d),qr(k);a--;c--;
		if(k==0){puts("0");continue;}
		a/=k,b/=k,c/=k,d/=k;
		ll ans=calc(a,c)+calc(b,d)-calc(a,d)-calc(b,c);
		printf("%lld\n",ans);
	}
	return 0;
}
发布了157 篇原创文章 · 获赞 129 · 访问量 1万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览