Bzoj 2342
Bzoj 2653

Bzoj 2301

coc youyl posted @ 2015年6月27日 18:54 in bzoj , 687 阅读

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2301

题目分类:数论,莫比乌斯反演

题意:

n个询问,每次询问有多少个数对(x,y)满足a<=x<=b且c<=y<=d且gcd(x,y)=k

题解:

使用容斥原理可以将问题转化成bzoj 1101这道题【f(b,d)-f(a-1,d)-f(b,c-1)+f(a-1,c-1)】

然后可以将问题转化成互质的数

可以通过一系列变换将式子转化为可以分块的式子

具体详见http://hzwer.com/4205.html

程序:

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
long long n,x1,x2,x3,x4,m;
long long miu[70000],isp[70000],cnt,pri[70000],summ[70000];
inline void shai()
{
	miu[1]=1;
	for (long long i=2;i<=60000;i++)
	{
		if(isp[i]==0){cnt++;pri[cnt]=i;miu[i]=-1;}
		for (long long j=1;j<=cnt&&i*pri[j]<=60000;j++)
		{
			isp[i*pri[j]]=1;
			if(i%pri[j]==0){miu[i*pri[j]]=0;break;}
			else miu[i*pri[j]]=-miu[i];
		}
	}
	for (long long i=1;i<=60000;i++)
	{
		summ[i]=summ[i-1]+miu[i];
	}
}
inline long long query(long long x,long long y)
{
	if(x>y)swap(x,y);
	long long pos=0,i=1,ans=0;
	while (i<=x)
	{
		pos=min(x/(x/i),y/(y/i));
		ans+=(summ[pos]-summ[i-1])*(x/i)*(y/i);
		i=pos+1;
	}//printf("%lld %lld %lld\n",x,y,ans);
	return ans;
}
int main()
{
	shai();
	scanf("%lld",&n);
	while (n--)
	{
		scanf("%lld %lld %lld %lld %lld",&x1,&x2,&x3,&x4,&m);
		x1--;x3--;
		printf("%lld\n",query(x2/m,x4/m)+query(x1/m,x3/m)-query(x1/m,x4/m)-query(x2/m,x3/m));
	}
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter