为了更加深入的理解和应用欧几里得和扩展欧几里得算法,选择这样的一个题目来进行详细讲述:
The equation http://acm.hust.edu.cn/vjudge/contest/view.action?cid=109329#problem/H
由于此题目需要分析的思路和过程比较多,除了代码实现外,我就直接手写了,字体有待改进,敬请谅解。
不带返回值的扩展欧几里得代码实现:(和上面相比,也算是另外一种编码方式了)
void extend_gcd(long long a,long long b,long long &x,long long &y)
{
if(b==0)
{
x=1;
y=0;
return;
}
extend_gcd(b,a%b,y,x);
y-=a/b*x;
return;
}
罗里吧嗦说了一堆,最后,代码实现如下:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
inline long long GMAX(long long &x,long long &y)
{
return x>y?x:y;
}
inline long long GMIN(long long &x,long long &y)
{
return x<y?x:y;
}
long long gcd(long long a, long long b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
void extend_gcd(long long a,long long b,long long &x,long long &y)
{
if(b==0)
{
x=1;
y=0;
return;
}
extend_gcd(b,a%b,y,x);
y-=a/b*x;
return;
}
int main()
{
long long a,b,c,x1,x2,y1,y2;
long long x0,y0;
while(scanf("%lld%lld%lld",&a,&b,&c)!=EOF)
{
scanf("%lld%lld",&x1,&x2);
scanf("%lld%lld",&y1,&y2);
c=-c;
if(c<0)
{
a=-a;
b=-b;
c=-c;
}
if(a<0) //相当于调换了x轴
{
a=-a;
long long t=x1;
x1=-x2;
x2=-t;
}
if(b<0)
{
b=-b;
long long t=y1;
y1=-y2;
y2=-t;
}
if(a==0 && b==0)
{
if(c==0)
{
printf("%lld\n",(x2-x1+1)*(y2-y1+1));
}
else printf("0\n");
}
else if(a==0)
{
if(c%b==0)
{
if(c/b>=y1&&c/b<=y2)
{
printf("%lld\n",x2-x1+1);
}
else printf("0\n");
}
else printf("0\n");
}
else if(b==0)
{
if(c%a==0)
{
if(c/a>=x1&&c/a<=x2)
{
printf("%lld\n",y2-y1+1);
}
else printf("0\n");
}
else printf("0\n");
}
else
{
long long M=gcd(a,b);
if(c%M)
{
printf("0\n");
}
a=a/M;
b=b/M;
c=c/M;
extend_gcd(a,b,x0,y0); //求的是=gcd(a,b)的值,所以下面要都*c
x0=x0*c;
y0=y0*c;
long long low1=ceil(1.0*(x1-x0)/b);
long long high1=floor(1.0*(x2-x0)/b);
long long low2=ceil(1.0*(y0-y2)/a);
long long high2=floor(1.0*(y0-y1)/a);
long long l=GMAX(low1,low2);
long long h=GMIN(high1,high2);
if(l>h)
{
printf("0\n");
}
else printf("%lld\n",h-l+1);
}
}
return 0;
}