/*
给出方程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;
}
计算最大公约数和不定方程
最新推荐文章于 2021-05-22 17:18:39 发布