欧几里得算法与不定方程

时间:2021-03-10 05:17:52

本文主要介绍数论中的欧几里得算法,线性方程及它们之间的关系。本文主要参考了《数论概论》,因此将本文当成这本书的读书笔记也未尝不可。

(本文正被完善中……)


欧几里得算法


问题:求60和22的最大公约数(两个数的最大公约数a, b是能够整除它们的最大数,记为gcd(a, b))。


因为这两个数比较小,所以我们完全可以通过肉眼观察出其最大公约数: 2 。那么对于( 225,120 )这一组数呢?我们可以分解两个数的因子:

225=32×52

120=23×3×5

然后求出所有数的约数( a 的约数 divisor(a) 表示能够整除 a 的数):

divisor(225)={1,3,5,9,15,25,45,75,225}

divisor(120)={1,2,3,4,5,6,8,10,12,15,20,24,30,40,60,120}

它们的公约数

commonDivisor(225,120)={1,3,5,15}

其中最大的 15 就是它们的最大公约数(根据最大公约数的定义)。大功告成,总算让人松了一口气。按照这个方法,不论来什么样的一组数,我们都可以轻松的求它们的最大公约数了。等等,真的是这样吗?那么来看看这一组数:

(1160718174,316258250)

我的天,这题谁爱算谁算吧(溜~)。

下面介绍欧几里得算法,只要掌握了这种算法,就可以用极其快的速度算出两个数的最大公约数,就算是上面那两个天文数字也 OK 。不仅如此,欧几里得算法还很容易通过编程实现,那么就可以利用计算机的计算能力迅速的解决大多数(指的是有机会碰上的)最大公约数的问题,其代码量只有三行。

在介绍算法的具体过程之前,我打算先用文字描述一下这个算法,即使无法很好的说清楚这个算法,也让先有一个大体的概念。

欧几里得算法:可以用以下方法求a, b的最大公约数gcd(a, b)

  1. 计算 r=amodb ,然后令 a=b,b=r
  2. 重复步骤 1 ,直到 r=0 ,此时 b 就是答案。

下面我们将利用欧几里得算法计算 gcd(1160718174,316258250)

1160718174=3  ×316258250+211943424

316258250  =1  ×211943424+104314826

211943424  =2  ×104314826+3313772

104314826  =31×3313772    +1587894

3313772      =2  ×1587894    +137984

1587894      =11×137984      +70070

137984        =1  ×70070        +67914

70070          =1  ×67914        +2156

67914          =31×2156          +1078 (最大公约数)

2156            =2  ×1078          +0

我们只用了 10 次计算就将这两个天文数字的最大公约数计算出来了。下面用一种不严谨的方法证明这种计算方法是对的(为了证明的方便,这里仅以上面的数据为例,不做一般性的证明):

先证明 1078 1160718174 316258250 的公约数:
1078 能够整除 2156 (最后一个式子)

因为 1078 能够整除 1078 2156 ,所以 1078 能够整除 67914 (倒数第二个式子)

……(以此类推)

因为 1078 能够整除 104314826 211943424 ,所以 1078 可以整除 316258250 (第二个式子)

因为 1078 能够整除 316258250 211943424 ,所以 1078 可以整除 1160718174 (第一个式子)

再证明 1078 是两数的公约数中最大的那个:

假设 d 为两数的任意公约数

因为 d 能够整除 1160718174 316258250 ,所以 d 能够整除 211943424 (第一个式子)

因为 d 能够整除 316258250 211943424 ,所以 d 能够整除 104314826 (第二个式子)

……(以此类推)

因为 d 能够整除 67914 2156 ,所以 d 能够整除 1078 (倒数第二个式子)

那么 1160718174 316258250 的任意公约数都能整除 1078 ,那么 1078 是两数的最大公约数。

简洁而神奇,这就是欧几里得算法。




扩展欧几里得算法


问题:求方程60x + 22y = gcd(60, 22)的一组解


这是个关于 x,y 的不定方程。我们观察这个方程。方程中有两个未知数,并且有一个奇怪的东西: gcd(60,22) 。为什么这个方程长得如此奇怪呢?这要从一条叫贝祖定理的定理说起:

贝祖定理:设a,b是不全为零的整数,则存在整数x,y,使得ax + by = gcd(a,b)

所以是因为这个方程的解一定存在,所以我们本着一颗“无聊的心”来考察一下这方程的如何求解。哈哈~

事实上ax + by的结果一定是gcd(a, b)的整数倍,所以如果要讨论ax + by这种整数线性方程的话,就必然要讨论这个方程

首先不管方程的解法如何,求出 gcd(60,22) 都是必须的。那我们在复习欧几里得算法的同时求一下 gcd(60,22)

a=60,b=22 (只是为了简洁),欧几里得算法的过程如下:

a=2×b+16

b=1×16+6

16=2×6+4

6=1×4+2 (最大公约数)

4=2×2+0

于是 gcd(a,b) 等于 2 。现在终于可以来解方程了。首先观察方程。显然,我们可以枚举 x,y 来求解,通过观察可以发现 4a+11b=2 。但是对于更一般的 a b ,用枚举的方法来解决问题就不一定有效了。这里就必须引入扩展欧几里得算法。同样,先介绍一下扩展欧几里得算法的大致步骤:

  1. 将欧几里得算法过程中的第一个式子中的 a, b, r 都用 a, b 表示
  2. 将第二个式子中的 a2, b2, r2 也用 a, b 表示
  3. 依次将第三,第四,…,第 m 式子中的 am, bm, rm a, b 表示
  4. 将倒数第二条式子中的所有量用 a, b 表示,此时可以得到方程的解

具体的步骤如下(下面的每条式子同上述欧几里得算法的每条式子相对应):

16=a2b

6=a+3b

4=3a8b

2=4a+11b

上面的最后一条式子就向我们展示了解。这就是扩展欧几里得算法。因为其正确性是显然的,所以这里就不证明了。


问题:求方程ax + by = gcd(a, b)的通解


如果求 60x+22y=2 的解还不够满足的话,我们可以将这个问题的更一般的解找出来。将方程一般化后可以得到方程: ax+by=g ,其中 g=gcd(a,b) 。我们尝试求出这条方程的所有解,也就是其通解。

首先,可以通过上述扩展欧几里得算法求出这条方程的一组解,我们可以将其记为 (x1,y1)

其次,我们可以先尝试求 g=1 的情况,也就是 a,b 互质(没有公共因子)的情况。显然,如果将 ax+by=1 的所有解 (x,y) 在平面直角坐标系中以点 (x,y) 的形式画出来,那么这些解一定落在直线 ax+by=1 上。以防有人不明白为什么这个方程的解集落在直线上,我们将方程变形为

y=abx+1b

这个“斜截式”的方程就比较显然的呈现出一条直线了。那么方程的另一组解就可以表示为直线上的另一个坐标为整数的点

(x1+t,y1abt)

其中 t 为某个神秘的我们暂时不需要知道是多少的整数。因为 g=gcd(a,b)=1 ,所以 为了保证“ abt 是整数“,必须满足“t为b的倍数” 。否则若 b 既不能整除 a 又不能整除 t ,则 abt 就 不是整数。

好的,现在 t b 的倍数了(之所以先讨论 g=1 , 目的就在于得到这个结论从而简化问题),那么t就可以表示为 k×b ,也就是 t=kb ,将 t 代入 (x1+t,y1abt) 可得方程的通解的形式

(x1+kb,y1ka)

其中 k 为任意整数,每个整数对应了方程的一组解。

然后,我们再讨论 g>1 的情况。先将方程 ax+by=g 变形:

agx+bgy=1

问题就转化成了上面一种情况,也就是 ax+by=1a=ag,b=bg,gcd(a,b)=1 的情况,那么套用前面的公式,通解就是

(x1+kbg,y1kag)


问题:求方程ax + by = c的通解

问题:求方程ax + by = g的最小非负解