解的个数(直线上的点)(数论-扩展欧几里得算法)

Description
  已知x,y满足如下条件:

  ax+by+c=0 ; x1 <= x <= x2 ; y1 <= y <= y2 ; x,y均为整数。

  其中:a,b,c,x1,x2,y1,y2 都是绝对值不超过 10^8 的整数。

  求(x,y)的解的个数。

Input

  第一行:n  说明:有 n 个任务。n<=10  一下有 n 行,每行为:a,b,c,x1,x2,y1,y2


Output

  有n行,第i行是第i个任务的结果。


分析:

裸的扩展欧几里得,但有几个坑点值得注意:

1,输入c之后直接 c=-c

2,a==0&&b==0的情况,还需要判断c==0

3,闭区间做减法还需要+1

4,正常情况下,求出了方程ax+by=c的一组解(注意不是ax+by=GCD(a,b)),x0和y0以及GCD(a,b)=g;设ap=a/g,bp=b/g,对于[x1~x2]来讲,这个k最小应该是(x1-x0)/bp 。一般可能会想到分别求x,y的k的范围然后求交集,但是考虑到可能除不尽,还有正负%@#*&¥#*%¥......所以就像李大神写的一样,枚举k就可以了,至于k需不需要加减1,顺便就判断了(不要问为什么用long long):

--------------------------------------------------

  LL bp=b/g,ap=a/g;
  LL k=(x1-x0)/bp;
  LL ans=0;
  for(;x0+k*bp<=x2;k++)
    if(y0-k*ap<=y2&&y0-k*ap>=y1&&x0+k*bp>=x1) //*
      ans++;


  printf("%lld\n",ans);

-----------------------------------------------------

注:上面*处, x0+k*bp>=x1 的判断就是为了避免k需要加减1带来的影响。


#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
LL n;
LL exgcd(LL a,LL b,LL &x,LL &y)
{
	if(b==0) {x=1;y=0;return a;}
	LL xx,yy,g=exgcd(b,a%b,xx,yy);
	x=yy;y=xx-(a/b)*yy;
	return g;
}
int main()
{
//	freopen("in.txt","r",stdin);
	scanf("%lld",&n);
	LL a,b,c,x1,x2,y1,y2;
	while(n--)
	{
		scanf("%lld%lld%lld%lld%lld%lld%lld",&a,&b,&c,&x1,&x2,&y1,&y2);
		c=-c;
		if(x1>x2||y1>y2)
		{
			printf("0\n");
			continue;
		}
		else if(a==0&&b==0)
		{
			if(c==0) printf("%lld\n",(y2-y1+1)*(x2-x1+1));
			else printf("0\n");
			continue;
		}
		else if(a==0&&b!=0)
		{
			if(c%b==0&&c/b>=y1&&c/b<=y2) printf("%lld\n",x2-x1+1);
			else printf("0\n");
			continue;
		}
		else if(a!=0&&b==0)
		{
			if(c%a==0&&c/a>=x1&&c/a<=x2) printf("%lld\n",y2-y1+1);
			else printf("0\n");
			continue;
		}
		LL x0,y0;
		LL g=exgcd(a,b,x0,y0);
		if(c%g!=0)
		{
			printf("0\n");
			continue;
		}
		x0=c*x0/g,y0=c*y0/g;
		LL bp=b/g,ap=a/g;
		LL k=(x1-x0)/bp;
		LL ans=0;
		for(;x0+k*bp<=x2;k++)
			if(y0-k*ap<=y2&&y0-k*ap>=y1&&x0+k*bp>=x1) 
				ans++;
		printf("%lld\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/wwwengine/article/details/81008388