SkyWT / 博客 / 欧几里德算法与拓展欧几里德算法略解

欧几里德算法与拓展欧几里德算法略解

2018 年 6 月 21 日 07:35


文章目录

欧几里德算法(Euclidean algorithm)又叫做辗转相除法,用于求最大公约数。这个算法已经十分常见了。扩展欧几里德算法(Extended Euclidean algorithm)是欧几里德算法的扩展(废话……),这个算法在解不定方程的时候十分常见。

本文中 (a,b) 或者 gcd(a,b) 表示 a、b 的最大公约数; a|b 表示 a 整除 b。

本文隶属⌈ 数论学习系列 ⌋。

欧几里德算法/辗转相除法

在数学中,辗转相除法,又称欧几里得算法(英语:Euclidean algorithm),是求最大公约数的算法。辗转相除法首次出现于欧几里得的《几何原本》(第VII卷,命题i和ii)中,而在中国则可以追溯至东汉出现的《九章算术》。、
——维基百科

代码

在我们日常的题目里辗转相除法已经十分常见了,最大公约数(Greatest Common Divisor)缩写为GCD,所以函数名就是gcd(当然扩欧的函数名就是exgcd)。其主要代码段是这样的:

int gcd(int a,int b){
    if (b==0) return a;
    return gcd(b,a%b);
}

以上代码其实可以写成以下这样:

int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}

原理和证明

辗转相除法的原理是什么呢?显然gcd(a,b)的作用是求出a、b的最大公约数(在数学语言里直接用(a,b)表示a、b的最大公约数)。如果b为0就返回a的值不难理解,这说明已经找到了最大公约数a。关键在于:

(a,b)=(b,amodb)(a,b) = (b,a \bmod b)

关于这个等式证明如下:

首先根据:

a=kb+r(a,b,k,rN+,r<b)a=kb+r (a,b,k,r \in N^+,r < b)

可以化为:

r=akb=amodbr=a-kb=a \bmod b

假设 dda,ba,b 的一个公约数,则 da,dbd \mid a , d \mid b。所以:

dakb    damodbd \mid a-kb \iff d \mid a \bmod b

即:

(a,b)    (b,amodb)(a,b) \iff (b,a \bmod b)

通俗点说,dda,ba,b 两个数的公约数,又是 b,amodbb,a \bmod b 的公约数,所以 a,ba,b 的公约数集与 b,amodbb,a \bmod b 的公约数集相同,它们的最大公约数必然也相同。

扩展欧几里德算法

扩展欧几里德算法(Extended Euclidean algorithm)就像是欧几里德算法的逆运算。

用途

主要有以下几种用途:

  1. 求解不定方程;
  2. 求解模线性方程(线性同余方程);
  3. 求解模的逆元。

求解不定方程的方法

个人觉得求解不定方程这个用途比较常见。可以方便地用来解这样的不定方程(传说中的裴蜀等式):

ax+by=cax+by=c

其实我们要解这个补不定方程,就要先解出 ax+by=gcd(a,b)ax+by=gcd(a,b)。基于这两个事实:

  1. 给予二个整数 a,ba,b,必存在整数 x,yx,y,使得 ax+by=gcd(a,b)ax+by=gcd(a,b)

  2. 对于方程 ax+by=cax+by=c,当且仅当 (a,b)c(a,b)|c 时这个方程有解。

容易证明,如果我们求出方程 ax+by=(a,b)ax+by=(a,b) 的一组特殊解 x0,y0x_0,y_0,则最后方程解为:

{x=x0+kb(a,b)y=y0ka(a,b)\begin{cases} x= x_0 +k \ast \frac b {(a,b)} \\ y= y_0 -k \ast \frac a {(a,b)} \end{cases}

那么如何“求出方程 ax+by=(a,b)ax+by=(a,b) 的一组特殊解”?这时候拓展欧几里德算法就派上用场了。

求解线性同余方程的方法

对于以下方程:

axb(modn)ax≡b \pmod n

如何求解这样的方程呢?其实这个方程可以看成:

ax+ny=b(x,yZ)ax+ny=b (x,y \in Z)

(注意 nn 一般是负数)这样就可以用不定方程的方法求解了!

代码

int exgcd(int a,int b,int &x,int &y){ //x、y变量用来传递求得的特殊解
    if(b==0){ //判断递归边界,b=0说明到底了
        x=1;y=0;
        return a;
    }
    int r=exgcd(b,a%b,x,y),t=x; //先递归把之前的都做完
    x=y;y=t-a/b*y;
    return r;
}

原理

先举个例子吧,求不定方程 1234x+4321y=11234x+4321y=1 的整数解。
首先求 (1234,4321)(1234,4321),过程如下:

(1234,4321)=(1234,619)=(615,619)=(615,4)=(3,4)=(3,1)=(0,1)=1(1234,4321)=(1234,619)=(615,619)=(615,4)=(3,4)=(3,1)=(0,1)=1

我们得到了 (1234,4321)=1(1234,4321)=1。接下来用扩展欧几里德算法可以倒着推回去:

1=10=1(331)=321=(423)3=433=4(6151534)=1544615=154(619615)615=154619155615=154619155(1234619)=3096191551234=309(432131234)1551234=309432110821234\begin{aligned} 1&=1- \underline 0 \\ &= 1-(3-3 \ast 1) = -3-2 \ast \underline 1 \\ &= (4-2 \ast 3)-3 = 4-3 \ast \underline 3 \\ &= 4 - (615-153 \ast 4) = 154 \ast \underline 4 - 615 \\ &= 154 \ast (619 - 615) - 615 = 154 \ast 619 - 155 \ast \underline {615} \\ &= 154 \ast 619 - 155 \ast (1234 - 619) = 309 \ast \underline {619} - 155 \ast 1234 \\ &= 309 \ast (4321-3 \ast 1234) -155 \ast 1234 = 309 \ast \underline {4321} -1082 \ast \underline {1234} \end{aligned}

所以这一组特解就是:x=1082,y=309x=-1082, y=309。按照这样的思路,前面的程序就不难理解了。先递归求 xxyy,再把 xx “复原”。

证明不会


暂无评论


发表新的评论

所有评论都将经过博主审核。请勿填写无意义邮箱或发表无关评论、广告等,否则会被视为垃圾评论。

提交评论即表明你同意本网站使用 Cookie,并允许本站在后台记录你的邮箱、IP 地址等必要信息。
(提交一次评论后,本提示将不再展示)