• 浅谈拓展欧几里得算法


    1、求特解 x 0 , y 0 x_0, y_0 x0,y0

    普通的欧几里得算法依据是辗转相除法,也就是,比如求 a , b a,b ab 的最大公约数, a , b a,b ab 进行辗转相除直到 a − b a-b ab 或者 b − a b-a ba 等于0,证明此时的原先 a , b a, b a,b 的最大公约数就是当前的 a a a,例子如下:

    a = 16, b = 6
    a > b, a = a - b = 10
    a > b, a = a - b = 4
    b > a, b = b - a = 2
    a > b, a = a - b = 2
    a = b = 2 = gcd(a, b)
    可见a > b必须减到a < b截至,
    故多步的减法可以合成一个 %
    int gcd(int a, int b) {
        return !b ? a : gcd(b, a % b);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述
    有了上面的了解,我们就可以知道,欧几里得算法的底层原理,那么思考下面一个问题,给出 a , b a, b a,b,求出一组特解 x 0 , y 0 x_0, y_0 x0,y0 满足下面表达式。
    a ∗ x + b ∗ y = g c d ( a , b ) a * x + b * y = gcd(a, b) ax+by=gcd(a,b)
    同样的,我们根据辗转相除法的思路,当 b = 0 b=0 b=0 的时候找到最大公约数,此时 a ∗ 1 + 0 ∗ y = g c d ( a , 0 ) = a a * 1 + 0 * y = gcd(a, 0) = a a1+0y=gcd(a,0)=a,故此时的 x = 1 , y = 0 x = 1, y = 0 x=1,y=0
    假如我们的递归如下:

    int exgcd(int a, int b, int x, int y) {
        if(!b) {
            x = 1, y = 0;
            return a;
        }
        int d = exgcd(b, a % b, y, x);
        y -= a / b * x;  // ?
        return d;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    ? ? ? 处为什么可以那样写,我们假定当前层:
    a ∗ x + b ∗ y = g c d ( a , b ) a * x + b * y = gcd(a, b) ax+by=gcd(a,b)
    下一层:
    b ∗ y + ( a − a / b ∗ b ) ∗ x = g c d ( a , b ) b * y + (a - a / b * b) * x = gcd(a, b) by+(aa/bb)x=gcd(a,b)
    化简:
    a ∗ x + b ∗ y − a / b ∗ b ∗ x = g c d ( a , b ) a * x + b * y - a / b * b * x = gcd(a, b) ax+bya/bbx=gcd(a,b)
    a ∗ x + b ( y − a / b ∗ x ) = g c d ( a , b ) a * x + b(y - a / b * x) = gcd(a, b) ax+b(ya/bx)=gcd(a,b)
    在这里插入图片描述

    2、求通解 x , y x, y x,y

    对于一般方程, a ∗ x + b ∗ y = c a * x + b * y = c ax+by=c,当 g c d ( a , b ) ∣ c gcd(a, b) | c gcd(a,b)c 时才有解,我们定义 d = g c d ( a , b ) d = gcd(a, b) d=gcd(a,b) 此时的解是:
    x 0 = x ∗ c / d x_0 = x * c / d x0=xc/d y 0 = y ∗ c / d y_0 = y * c / d y0=yc/d
    对于特解 x 0 , y 0 x_0, y_0 x0,y0 x 0 x_0 x0 移动 n n n 格:
    x = x 0 + n x = x_0 + n x=x0+n
    ( x 0 + n ) ∗ a + y ∗ b = d (x_0 + n) * a + y * b = d (x0+n)a+yb=d
    y = y 0 − a / b ∗ n y = y0 - a / b * n y=y0a/bn
    转化后:
    x = x 0 + b ∗ n x = x_0 + b * n x=x0+bn
    y = y 0 − a ∗ n y = y_0 - a * n y=y0an
    发现 x x x 每次变化 b b b 个单位并不是最小单位,故通解如下:
    x = x 0 + b / d ∗ k x = x_0 + b / d * k x=x0+b/dk
    y = y 0 − a / d ∗ k y = y_0 - a / d * k y=y0a/dk

    3、求最小正整数解

    通解得到之后,如果 x > 0 x > 0 x>0 那么最小正整数解就是 x % ( b / d ) x \% (b / d) x%(b/d)
    否则最小正整数解就是 ( x % ( b / d ) + ( b / d ) ) % ( b / d ) (x \% (b / d) + (b / d)) \% (b / d) (x%(b/d)+(b/d))%(b/d)
    故最小正整数解就是 ( x % ( b / d ) + ( b / d ) ) % ( b / d ) (x \% (b / d) + (b / d)) \% (b / d) (x%(b/d)+(b/d))%(b/d)

  • 相关阅读:
    HTML5+CSS3小实例:纯CSS实现奥运五环
    【LeetCode】Day139-打家劫舍 III
    猿创征文丨深度学习基于双向LSTM模型完成文本分类任务
    Docker安装、入门及VSCode链接(地平线OE docker镜像)
    nodejs+vue+elementui数字化家谱网站管理系统express
    LAMP环境部署:安装Discuz
    电脑主机如何选择内存条
    SQL教育行业案例:学员续费如何分析?(case when、窗口函数)
    2022年最新全国各省五级行政区划代码及名称数据(省-市-区县-乡镇-村)
    新款UI动态壁纸头像潮图小程序源码
  • 原文地址:https://blog.csdn.net/cjp_kangkang_/article/details/132916319