为了更加深入的理解和应用欧几里得和扩展欧几里得算法,选择这样的一个题目来进行详细讲述:
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; }