扩展欧几里得算法

来源:互联网 发布:淘宝打假赚钱怎么赚钱 编辑:程序博客网 时间:2024/05/18 00:57

——by《紫书》


问题引入:

直线上的点。求直线ax+by+c=0上有多少个整点(x,y)满足x∈[x1,x2],y∈[y1,y2]。


分析:

这里先介绍本问题核心的算法——扩展欧几里得算法

  • 扩展欧几里得算法:
    找出一对整数(x,y),使得ax+by=gcd(a,b)。这里的x和y不一定是整数,也可能是0或负数。
    ax+by = gcd(a,b)这个式子总是有解
void gcd(int a, int b, int &d, int &x, int &y){    if(!b){        d = a; x = 1; y = 0;//gcd(a,0)=1*a-0*0=a    }else{        gcd(b, a%b, d, y, x);        y -= x*(a/b);    }}

x和y就是ax+by = gcd(a,b)的其中一个解,d是gcd(a,b)

现在求的只是一个解,那么还有其他解吗?当然,还有无数个!
设a,b,c为任意整数。若方程ax+by=c的一组整数解为(x0,y0),则它的任意整数解都可以写成(x0+kb’ , y0-ka’),其中a’= a/gcd(a,b) , b’= b/gcd(a,b),k为任意整数。

那么原问题就可以通过扩展欧几里得算法解决了。
原问题是求ax+by+c=0的解。移项得ax+by = -c。那么如果c是gcd(a,b)的倍数,那么就一定有解。
设a,b,c为任意整数,g = gcd(a,b),方程ax+by=g的一组解是(x0,y0),则当c是g的倍数时,ax+by=c的一组解是(x0c/g , y0c/g);当c不是g的倍数时无整数解。

代码如下:

#include<cstdio>using namespace std;const int INF = 1000; void gcd(int a, int b, int &d, int &x, int &y){    if(!b)    {        d = a; x = 1; y = 0;    }else{        gcd(b, a%b, d, y, x);        y -= x*(a/b);    }}int main(){    int a,b,c,d;    scanf("%d%d%d",&a,&b,&c);             int x1,x2,y1,y2;    scanf("%d%d%d%d",&x1,&x2,&y1,&y2);//整点的范围     int x0,y0;                       //ax+by=gcd(a,b)的一个解     gcd(a,b,d,x0,y0);     int a2 = a/d, b2 = b/d;         //其他解     int count = 0;     if(c%d==0)    {        for(int k=0; k<INF; k++)        {            x0 = x0+k*b2;            y0 = y0-k*a2;            if(x0<x1||x0>x2||y0<y1||y0>y2)            continue;            count++;        }    }    printf("%d\n",count);    return 0;}
0 0