数论:拓展欧几里得求解二元一次不定方程

拓展欧几里得算法求解二元一次不定方程


本节内容,主要围绕 为什么、怎么做、怎么写 这三个关系来讲解。

为什么?

为什么拓展欧几里得算法可以求二元一次不定方程的解?

首先明确:对于任意的 a x + b y = c ax+by=c ax+by=c都可以转化为 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的求解。

所以只需要关注: a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的求解过程即可。

而对于 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的求解,也只是在 a ′ x + b ′ y = 1 a'x+b'y=1 ax+by=1的基础上进行的拓展。

所以本质就是用 e x g c d exgcd exgcd求解 a ′ x + b ′ y = 1 a'x+b'y=1 ax+by=1

裴蜀定理可知,若 g c d ( a , b ) = d gcd(a,b)=d gcd(a,b)=d,则一定存在一组整数解 ( x , y ) (x,y) (x,y)满足 a x + b y = d ax+by=d ax+by=d​。

由欧几里得算法: g c d ( a , b ) = g c d ( b , a   m o d   b ) gcd(a,b)=gcd(b,a\:mod\:b) gcd(a,b)=gcd(b,amodb)

所以,原问题求 ( a x + b y = d ) (ax+by=d) (ax+by=d)的通解,等价于求: b x + ( a   m o d   b ) y = d bx+(a\:mod\:b)y=d bx+(amodb)y=d的通解。

而求 b x + ( a   m o d   b ) y = d bx+(a\:mod\:b)y=d bx+(amodb)y=d的通解,等价于求 ( a   m o d   b ) x + b   m o d   ( a   m o d   b ) y = d (a\:mod\:b)x + b\:mod\:(a\:mod\:b)y=d (amodb)x+bmod(amodb)y=d的通解…。

很眼熟对吧?这类似于欧几里得算法的求解过程,这个步骤是有限的,我们只要不断的递归下去,一定有尽头。

尽头就是: b = 0 b=0 b=0

当我们求到尽头的时候,原方程转化为: a ′ x = d a'x=d ax=d 有整数解,解为: x = d a ′ x=\frac{d}{a'} x=ad

一个约定俗成的事是可以直接令 x = 1 , y = 0 x=1,y=0 x=1,y=0

我们一般关注的不是特解,而是通解/最小正整数解,所以特解是什么都无所谓。

怎么做?

我们发现,即使我们不知道 a x + b y = c ax+by=c ax+by=c的解,我们仍然可以通过上述方法不断迭代,直到迭代到尽头。此时,我们就可以求出

考虑任意两层 ( x , y ) (x,y) (x,y)之间的转化:

设当前层为: ( x 1 , y 1 ) (x_1,y_1) (x1,y1),下一层为: ( x 2 , y 2 ) (x_2,y_2) (x2,y2)

联立:
{ a x 1 + b y 1 = d b x 2 + [ a   m o d   b ] y 2 = d \begin{cases} ax_1+by_1=d \\ bx_2+[a\:mod\:b]y_2=d \end{cases} {ax1+by1=dbx2+[amodb]y2=d
中间状态:
{ a x 1 + b y 1 = d 1 b x 2 + ( a − [ a b ] ∗ b ) y 2 = d → a y 2 + b ( x 2 − [ a b ] y 2 ) = d \begin{cases} ax_1+by_1=d1\\ bx_2+(a-[\frac{a}{b}]*b)y_2=d\rightarrow ay_2+b(x_2-[\frac{a}{b}]y_2)=d \end{cases} {ax1+by1=d1bx2+(a[ba]b)y2=day2+b(x2[ba]y2)=d
系数对齐:
{ a x 1 + b y 1 = d a y 2 + b ( x 2 − [ a b ] y 2 ) = d \begin{cases} ax_1+by_1=d\\ ay_2+b(x_2-[\frac{a}{b}]y_2)=d \end{cases} {ax1+by1=day2+b(x2[ba]y2)=d

得到了相邻两层之间的整数解 ( x , y ) (x,y) (x,y)的转移方程:
{ x 1 = y 2 y 1 = x 2 − [ a b ] y 2 \begin{cases} x_1=y_2\\ y_1=x_2-[\frac{a}{b}]y_2 \end{cases} {x1=y2y1=x2[ba]y2
先直接地给出代码:

int exgcd (int a, int b, int &x, int &y) {
        if (!b) {x = 1; y = 0; return a;}
        int d = exgcd (b, a % b, x, y);
        int x2 = x, y2 = y;
        x = y2, y = x2 - a / b * y2; 
        return d;
}
怎么写?

对于第i层, x i = y i + 1 x_i=y_{i+1} xi=yi+1,因为算法的特性,我们一开始并不知道 x , y x,y x,y的值,所以我们不能对其进行任

何运算,而是需要递归到底部对 x , y x,y x,y进行初始化,并在回溯过程中才能更新每一层的 x , y x,y x,y。(要完成这样的操作,我们需要传入 x , y x,y x,y​的引用。)

而回溯的时候, x , y x,y x,y 的状态都是上一层的状态: ( x 2 , y 2 ) (x_2,y_2) (x2,y2)表示上一层的 ( x , y ) (x,y) (x,y)

int x2 = x, y2 = y;
x = y2, y = x2 - a / b * y2; 

这并不难记,一旦忘记了相邻两层之间的 x , y x,y x,y的传递关系,利用欧几里得算法推导即可。
{ a x 1 + b y 1 = d b x 2 + [ a   m o d   b ] y 2 = d \begin{cases} ax_1+by_1=d \\ bx_2+[a\:mod\:b]y_2=d \end{cases} {ax1+by1=dbx2+[amodb]y2=d
正常我们直接抄板子就行了:

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

值得注意的是,我们求出来的 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)是关于方程: a x + b y = 1 ax+by=1 ax+by=1 的一个解。

如何去求通解?

其实通过数学直觉,我们不难想出,如果 x x x增加 Δ x \Delta x Δx , 相当于方程左边增加了 a Δ x a \Delta x aΔx ,我们要想方程右边不变的话,设让 y y y减去 Δ y \Delta y Δy

a ( x + Δ x ) + b ( y − Δ y ) = 1 a(x+\Delta x) + b(y-\Delta y)=1 a(x+Δx)+b(yΔy)=1

可以得到等式: a Δ x = b Δ y a\Delta x = b\Delta y aΔx=bΔy

∴ Δ x Δ y = b a \therefore \frac{\Delta x}{\Delta y}=\frac{b}{a} ΔyΔx=ab

接下来我们将右边的分式约分为最简式子即可: b a = b g c d ( a , b ) a g c d ( a , b ) \frac{b}{a}=\frac{\frac{b}{gcd(a,b)}}{\frac{a}{gcd(a,b)}} ab=gcd(a,b)agcd(a,b)b

即除以它们的最大公约数。

通解:
{ x = x 1 + b g c d ( a , b ) × k y = y 1 − a g c d ( a , b ) × k \begin{cases} x=x_1+\frac{b}{gcd(a,b)}\times k\\ y=y_1-\frac{a}{gcd(a,b)}\times k \end{cases} {x=x1+gcd(a,b)b×ky=y1gcd(a,b)a×k

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

louisdlee.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值