扩展欧几里得算法

    xiaoxiao2021-04-15  58

    ——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; }
    转载请注明原文地址: https://ju.6miu.com/read-670899.html

    最新回复(0)