• 欧几里德及扩展欧几里德——详解


    欧几里德定理:

      对于整数a, b来说有,gcd (a, b) == gcd (b, a%b) == d,又称为辗转相除法。

    欧几里德证明:

      先进行设定:x, y, t, k 为整数,并且有d*x == a, d*y == b. t = a - b. k = a / b。

      那么t = d*x - d*k*y; t = d * (x - k * y); 故 t % d == 0;

      所以gcd (b, t) == d == gcd (b, a%b) == gcd (a, b);

      证毕。

    欧几里德应用:

      用来求a,b的最大公约数。

    代码实现:

    1 int gcd (int a, int b)
    2 {
    3     return b ? gcd (b, a % b) : a;
    4 }

    扩展欧几里德定理:

      对于不完全为零的非负整数a, b。必定存在整数x, y,满足a*x + b*y == gcd (a, b) == b;

    扩展欧几里德证明:

      A.  我们知道对于gcd (a, 0) == a, 那么 a*x + b*y == a, 可以解出x = 1, y = 0。

      B. 对于a, b都不等于零的情况来说:

        a*x1 + b*y1 = gcd (a, b);

        b*x2 + (a%b)*y2 = gcd (b, a%b);

        欧几里德告诉我们gcd (a, b) == gcd (b, a%b), 那么我们对上面两个式子进行转化:

        a*x1 + b*y1 == b*x2 + (a%b)*y2;

        b*x2 + (a%b)*y2 == b*x2 + (a - a/b*b)*y2 == b*x2 + a*y2 - a/b*b*y2 == a*y2 + b*(x2 - a/b*y2)

        得出:a*y2 + b*(x2 - a/b*y2) = a*x1 + b*y1,在根据恒等定理可以等到:x1 == y2, y1 == x2 - a/b*y2;

        可以看出,x1, y2是基于x2,y2的。那么我们一次一次向下取余的话,根据基本欧几里德定理可知,总会有一次b == 0的。那么x1, y1 就肯定有解咯!

    扩展欧几里德应用:

      1:求解一元线性同余方程,如解决中国剩余定理问题。

      2:求解不定方程,比如说对于:a*x + b*y = c, 如果c % gcd (a, b) == 0, 则对于x, y有解,否则无解。

        那么问题来了,有解的话要怎么求解呢?

        已知扩展欧几里德定理,我们可以求出x0, y0满足:a*x0 + b*y0 == gcd (a, b)

        那么对于a*x1 + b*y1 == c来说,x1 = x0 * c / gcd (a, b), y1 = y0 *c / gcd (a, b);

        对于x, y对应的解集就是:

                        x = x1 + b / gcd (a, b) * t;

                        y = y1 - a / gcd (a, b) * t;(t是任意的自然数)

    扩展欧几里德实现:

     1 LL Extended_Euclid (LL a, LL b, LL &x, LL &y)
     2 {//处理 a * b > 0 的情况
     3     if (b == 0)
     4     {
     5         x = 1;
     6         y = 0;
     7         return a;
     8     }
     9 
    10     LL r = Extended_Euclid (b, a%b, x, y), t;
    11     t = x;
    12     x = y;
    13     y = t - a / b * y;
    14     return r;
    15 }

    当a, b不同号的话,上面的推论就有一点问题了,在用恒等定理的时候x, y 也应该换号

     1 LL Extended_Euclid (LL a, LL b, LL &x, LL &y)
     2 {//可以处理所有的情况
     3     if (b == 0)
     4     {
     5         x = 1;
     6         y = 0;
     7         return a;
     8     }
     9 
    10     LL r = Extended_Euclid (b, a%b, x, y), t;
    11     t = x;
    12     if (a * b < 0)
    13     {
    14         x = -y;
    15         y = a / b * y - t;
    16     }
    17     else
    18     {
    19         x = y;
    20         y = t - a / b * y;
    21     }
    22     return r;
    23 }

        

    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    luogu P1451 求细胞数量
    P1443 马的遍历
    luogu P1194 买礼物
    codevs 4919 线段树练习4
    printf的实型
    printf的整型
    scanf
    printf
    c++常用函数
    字符类型C++(ascll码表)
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4819223.html
Copyright © 2020-2023  润新知