浅谈拓展欧几里得算法

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);
}

在这里插入图片描述
有了上面的了解,我们就可以知道,欧几里得算法的底层原理,那么思考下面一个问题,给出 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;
}

? ? ? 处为什么可以那样写,我们假定当前层:
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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值