计算最大公约数和不定方程

/*
给出方程ax+bx+c=0,求出有多少对整数解(x,y),满足X1<=x<=X2,Y1<=y<=Y2.
输入:a,b,c,X1,X2,Y1,Y2,所有数的绝对值都小于10^8。
输出:直接输出答案
*/
/*
  a mod b=a-(int)(a/b)*b;
  (ax+by)=gcd(a,b)
   gcd(a,b)=a x=1,y=0;
方程若有整数解,必须满足如下条件:
首先使用欧几里得算法的推广形式计算初始解x0,y0和gcd(a,b);
1.直接求解a=b=0的特例(gcd(a,b)==0));
  *若常数c=0,则根据乘法原理,x和y取值范围内整数个数的乘积((X2-X1+1)*(Y2-Y1+1))为整数解的对数
  *若常数c!=0,则方程不成立,无解退出
2.若c不能整除gcd(a,b),则方程不成立,无解退出。
3.将方程ax+by+c=0转换为ax+by=-c;((ax+by)=gcd(a,b))
  通解{x=x0+t*△x
      {y=y0+t*△y
  x0=x0*(-c/gcd(a,b)),y0=y0*(-c/gcd(a,b))
  △x=lcm(a,b)/a(或b/gcd(a,b)),△y=-lcm(a,b)/b(或-a/gcd(a,b));
  计算x所在的区间[lx,rx]={【[(X1-x0)/△x],[(X2-x0)/△x]】△x>0
                         {【[(X2-x0)/△x],[(X1-x0)/△x]】△x<=0。若lx<rx,则x无解,失败退出。
  计算x所在的区间[ly,ry]={【[(Y1-x0)/△y],[(Y2-x0)/△y]】△y>0
                         {【[(Y2-x0)/△y],[(Y1-x0)/△y]】△y<=0。若lx<rx,则x无解,失败退出。
  计算两个区间的交集[lp,rp]={max{lx,ly},min{rx,ry}.若两个区间无交集(lp>rp),则失败退出;
  否则整数解的对数为公共区间中整数解的个数rp-lp+1.
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
__int64 a,b,c,x1,x2,Y1,y2;
__int64 exgcd(__int64 a,__int64 b,__int64 &x,__int64 &y)
{
	if(!b)
	{
		x=1,y=0;
		return a;
	}
	else
	{
		__int64 ret=exgcd(b,a%b,y,x);
		y-=a/b*x;
		return ret;
	}
}
int main()
{
	scanf("%I64d%I64d%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&x1,&x2,&Y1,&y2);
    c*=-1;
	__int64 x,y,r,dx,dy;
	r=exgcd(a,b,x,y);
	if(r==0)
	{
		if(c==0) printf("I64d\n",(x2-x1+1)*(y2-Y1+1));
		else cout<<0<<endl;
		return 0;
	}
	if(c%r!=0){
		cout<<0<<endl;
	}
	x*=c/r;y*=c/r;
	dx=b/r,dy=a/r*-1;
	__int64 lx,ly,rx,ry;
	x1-=x,x2-=x,Y1-=y,y2-=y;
	if(dx>0)
	{
		lx=ceil(double(x1)/dx),rx=floor(double(x2)/dx);
	}
	else
	{
        lx=ceil(double(x2)/dx),rx=floor(double(x1)/dx);
	}
	if(dy>0)
	{
		ly=ceil(double(Y1)/dy),ry=floor(double(y2)/dy);
	}
	else
	{
        ly=ceil(double(y2)/dy),ry=floor(double(Y1)/dy);
	}
	__int64 lp=lx>ly?lx:ly;
	__int64 rp=rx<ry?rx:ry;
	if(rx<lx||ry<ly||rp<lp) 
		cout<<0<<endl;
	else 
		printf("%I64d\n",rp-lp+1);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

u014068781

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值