擴展歐幾里得演算法(EXGCD)學習筆記

  • 2021 年 3 月 15 日
  • 筆記

0.前言

相信大家對於歐幾里得演算法都已經很熟悉了。再學習數論的過程中,我們會用到擴展歐幾里得演算法(exgcd),大家一定也了解過。這是本蒟蒻在學習擴展歐幾里得演算法過程中的思考與探索過程。

1.Bézout定理

擴展歐幾里得演算法利用歸納法,證明了Bézout定理。

Bézout定理:對於任意整數 \(a\),\(b\) ,存在一對整數 \(x\),\(y\),滿足 \(ax+by=gcd(a,b)\)
在擴展歐幾里得的演算法中,我們求出 \(x\),\(y\) 的值。

2.證明

2.1 \(gcd\)

首先,我們來看一下 \(gcd\) 函數

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

在第二行,也就是遞歸終止時,\(b=0\)\(a=gcd(a,b)\)。 我們可以發現存在一對整數 \(x\),\(y\) 滿足條件 \(ax+by=gcd(a,b)\)
將已知的值代入可得:\(ax+b*0=gcd(a,b)\)
\(a=gcd(a,b)\)
\(gcd(a,b)*x=gcd(a,b)\)
\(y\)在終止時可取任意值,\(x=1\)

2.2歸納法

我們在2.1中得到了 \(b=0\) 時的解。現在,我們用歸納法一步步得到最終解。當 \(b>0\) 時,我們假設 \(b*x\) 滿足條件 \(b*x+(a\,mod\,b*y)gcd(b,a\,mod\,b)\)(代入的值也正是我們平時進行gcd的轉移方程)
\(∵ bx+(a\,mod\,b)y=bx+[a-b(a/b)]y\)
\(∴ bx+(a\,mod\,b)y=bx+ay-by(a/b)\)
\(∴ bx+(a\,mod\,b)y=ay+bx-by(a/b)\)
\(∴ bx+(a\,mod\,b)y=ay+b[x-(a/b)y]\)
\(x_1=y\), \(y_1=x-(a\,mod\,b)y\),再代入已得到的式子,就能得到:
\(ax_1+by_1=gcd(a,b)\),所以可以得出Bézout定理成立。

3.程式碼實現

3.1思路簡述

我們的程式碼在截止條件上與 \(gcd\) 相同,都是 if(b == 0)時停止遞歸。我們在此基礎上再改變 \(x\)\(y\) 的值。

3.2參考程式碼及注釋

大部分都按照前面的推導過程

int exgcd(int a, int b, int &x, int &y) { //x,y的初始值無關
	if(b == 0) {
		x = 1, y = 0;//改變x,y的值(y可取任意值)
		return a;
	} else {
		int tmp = exgcd(b, a % b, x, y);//保存下一次的最大公約數
		int z = x; //存儲上一次的x
		y = x; //及上文中的y1
		x = z - y * (a / b); //及上文中的x_1
		return tmp;//返回最大公約數
	}
}