漫談最大公因數
許介彥
大葉大學 通訊與計算機工程學系
某 天 , 小 明 帶 著 兩 個 空 桶 子 到 河 邊 提 水,兩個桶子上都沒有刻度,不過容量已知 分別為 15 公升和 27 公升;小明想要取得不 多不少正好 6 公升的河水,他該怎麼做?歐幾里得演算法
以上所述是一個與最大公因數(greatest common divisor,簡稱 g.c.d.)有關的問題。 我們在中學學過,任意兩個正整數的最大公 因數可以利用「輾轉相除法」求得。舉例來 說,以下所示為以輾轉相除法求出 477 與 138 的最大公因數(等於 3)的過程: 477 3 0 12 12 126 138 3 60 63 414 5 2 4 其中的各個階段可以用數學式來表示: 3 4 5 2 3 12 63 138 + + + + 63 12 3 0 = = = = 477 12 63 138 ⋅ ⋅ ⋅ ⋅ 或者再換個方式: 階段 1 4 3 2 被除數 477 12 63 138 除數 138 3 12 63 餘數 63 12 3 0 商 3 2 5 4 由上表很明顯可以看出,除了第一個階 段外,其他各階段的被除數與除數分別是來 自前一個階段的除數與餘數,而當某個階段 的餘數為 0 時整個計算即告結束,而且該階 段的除數就是原來的兩數的最大公因數。為 什麼會這樣呢? 對任意正整數 a 與 b ,如果我們將 a 除 以 b 的商及餘數分別記作 q 及 r(餘數 r 的值 須滿足0≤r<b),也就是 r b q a= ⋅ + 那麼不難証明,a 與 b 的最大公因數會 等於 b 與 r 的最大公因數。要証明這個性質 可依下列三個步驟來完成: 1. 說明 a 與 b 的公因數必是 r 的因數。 2. 說明 b 與 r 的公因數必是 a 的因數。 3. 由以上 1 與 2 可知 a 與 b 所有的公因數和 b 與 r 所有的公因數相同,因此 a 與 b 和 b 與 r 有相同的「最大」公因數。 以前面的例子為例,如果我們將 a 與 b 的最大公因數記作gcd( ba, ),那麼前面的運 算過程其實是持續地在簡化用來求最大公因 數的兩個整數: 3 ) 3 , 12 gcd( ) 12 , 63 gcd( ) 63 , 138 gcd( ) 138 , 477 gcd( = = = =一般而言,對任意正整數 a 與 b ,我們 可以將輾轉相除法的各個階段以數學式子表 示: M = q1 a = q2 b = q3 r1 = q4 r2 ⋅ ⋅ ⋅ ⋅ b r1 r2 r3 + + + + r1 r2 r3 r4 (0 < r1 < b) (0 < r2 < r1) (0 < r3 < r2) (0 < r4 < r3) 並且讓計算一直持續到餘數為 0 為止。經由 審視各階段的餘數間的大小關係,我們發覺 必然會在某個階段出現餘數為 0 的情形,因 為除了最後一個階段以外,各階段的餘數都 是正數而且越來越小: 0 4 3 2 1> > > > > >r r r r L b 因此頂多經過 b 個階段,必定會出現餘 數為 0 的情形: ⋅ (0 < rn < rn-1) M = + rn-2 rn rn-1= qn qn+1 rn-1 rn ⋅ 這時候我們就知道 a 與 b 的最大公因數等於 rn,也就是當餘數為 0 時的除數,亦即這一 系列計算中的最後一個大於 0 的餘數,因為 n n n r r r r r r r r b b a = = = = = = − , ) gcd( ) , gcd( ) , gcd( ) , gcd( ) , gcd( 1 3 2 2 1 1 K 上述做法一般認為是由西元前三世紀的 希臘大數學家歐幾里得(Euclid )發明的, 因 此 常 被 稱 為 歐 幾 里 得 演 算 法 ( Euclidean algorithm),其運算步驟可以簡潔地表達成以 下的遞迴演算法: GCD( a, b) if b = 0 return a else return GCD( b, a mod b)
其中的 mod 是取餘數的運算,a mod b 的結 果為 a 除以 b 的餘數。
歐幾里得演算法的應用
(一)將
a /b表為連分數
歐幾里得演算法可以用來將兩個正整 數 相 除 的 結 果 表 示 成 連 分 數 ( continued fractions),也就是形如 L + + + + 3 2 1 0 1 1 1 a a a a 的分數,其中除了a 之外,所有的0 a 都是n 正整數。以我們前面看過的求gcd(477,138) 的例子為例,477/138的值很容易可以被表 示成連分數: 138 477 138 63 3+ = 63 138 1 3+ = 63 12 2 1 3 + + = 12 63 1 2 1 3 + + = 12 3 5 1 2 1 3 + + + = 3 12 1 5 1 2 1 3 + + + =4 1 5 1 2 1 3 + + + = 很明顯,最後結果的整數部份a0、a1、 2 a 、a3、…(此例中的 3、2、5、4)正好是 歐幾里得演算法的計算過程中各階段的商。 連分數的用途之一是用來做為兩數相除 結果的近似值。以477/138(分子與分母約 掉公因數 3 後成為159/46)為例,在以上將 其表為連分數的過程中,如果我們在各階段 將 還 沒 算 完 的 部 分 捨 棄 , 可 分 別 得 到 一 個 46 / 159 的「近似值」: 階段 近似值 1 3 2 2 7 2 1 3+ = 3 11 38 5 1 2 1 3 = + + 4 46 159 4 1 5 1 2 1 3 = + + + 其中, 46 159 46 159 46 159 11 38 46 159 2 7 46 159 3 = < > < 一般而言,第一個階段的近似值會比實 際 值 小 , 第 二 個 階 段 的 近 似 值 會 比 實 際 值 大,第三個階段的近似值又較小,第四個階 段的近似值又較大 ……,與實際值相比,大 小關係是交替的,所有奇數階段都比實際值 小,偶數階段都比實際值大,直到最後一個 階 段 才 與 實 際 值 相 等 。 因 此 , 以159/46為 例,如果我們想要取一個比實際值稍大且數 字較簡單的值來做為近似值,可以取7/2(誤 差約為 1.3% ),而如果想要取一個比實際值 小 的 近 似 值 , 可 以 取 38/11( 誤 差 約 為 0.057% )。
(二)求
ax+by=c的整數解
歐幾里得演算法的另一個應用是可以求 得形如ax+by=c的方程式的整數解,其中 的 a 、b 、c 都是已知的正整數而 x 與 y 為未 知 整 數 ; 這 種 方 程 式 在 數 學 上 稱 為 linear Diophantine equation(Diophantus 為西元三世 紀的希臘數學家,一般譯為丟番圖);當它有 解時,必有無窮多組解,不過也可能沒有任 何整數解。 在說明如何求解之前,讓我們先看一個 相關的性質:如果d =gcd( ba, ),那麼方程式 d by ax+ = 必定存在整數解 , 也 就 是 說 ,d 必 可 表 示 成 a 與 b 的 線 性 組 合 ( linear combination )。歐幾里得演算法可以幫助我們 很容易地找到ax+by=d的一組解;而有了 一組解後,再找其他解就不難了。 用前面看過的3=gcd(477,138)為例,上 面 的 性 質 是 說 477x+138y=3一 定 有 整 數 解。我們在前面曾經將求 477 與 138 的最大 公因數的各個階段以數學式表示;如果我們 將各式的餘數寫在等號左邊,其他項移到等 號右邊,將得 ⋅ 63 = 477 − 3 12 = 138 − 2 3 = 63 − 5 ⋅ ⋅ 138 63 12前面提過,歐幾里得演算法的計算過程是在 將數字持續簡化,而我們現在要做的工作則 是相反,是要由最大公因數 3 開始「反推」 回去,讓數字由簡單而複雜,直到能將 3 用 最初的 477 與 138 表示為止: 138 38 477 11 138 5 ) 138 3 477 ( 11 138 5 63 11 ) 63 2 138 ( 5 63 12 5 63 3 ⋅ − ⋅ = ⋅ − ⋅ − ⋅ = ⋅ − ⋅ = ⋅ − ⋅ − = ⋅ − = 因此我們找到了方程式477x+138y=3的一 組 整 數 解 : x0 =11及 y0 =−38, 或 者 寫 為 ) 38 , 11 ( ) , (x0 y0 = − 。 其 他 的 整 數 解 要 怎 麼 求 呢 ? 假 設 ) , (x1 y1 是任意另外一組解,由 = + = + d by ax d by ax 0 0 1 1 兩式相減,得 0 ) ( ) (x1−x0 +b y1−y0 = a 因 此 (x1−x0,y1−y0) 必 為 ax+by=0 的 解;又由於方程式ax+by=0的解必可寫為 n d b x= , n d a y=− (n 為任意整數),因此我們可以讓 n d b x x1− 0 = , n d a y y1− 0 =− 而得 n d b x x1= 0+ , n d a y y1= 0− 因此方程式ax+by =d的一般解為 n d b x x= 0+ , n d a y y= 0− 方 程 式 477x+138y=3 的 一 般 解 因 此 為 ) , (x y = (11+46n,−38−159n)。 接著我們回到原來的方程式 ax + by = c。假設d =gcd( ba, ),由於ax+by一定是 d 的倍數,因此 c 一定也是 d 的倍數,否則 a x + b y = c 不可能有整數解。另一方面,是不是 只要 c 是 d 的倍數,ax+by=c就一定有整 數解呢? 答案是肯定的, 因為如果(x0,y0)是 ax + by = d 的一組解,而且 c 是 d 的 m 倍 (c= md),則 d by ax0+ 0 = ⇒a(mx0)+b(my0)=c ⇒(mx0,my0)是ax+by=c的一組解 因此,我們有了以下的結論:ax + b y = c 有整數解 「若且唯若」c 是 d 的整數倍。如 果 c 是 d 的 m 倍且(x0,y0)是ax+by =d的 一組解,那麼ax+by=c的一般解為 n d b mx x= 0+ , n d a my y= 0− 舉例來說,477x+138y=9的一般解為(x,y) = (33+46n,−114−159n)。
歐幾里得演算法的擴充
由已知的 a 與 b 想求得方程式ax+by = d(d 等於 gcd( ba, ))的一組解,除了前述 分 為 兩 個 階 段( 先 由 歐 幾 里 得 演 算 法 求 出 d,再由 d 反推回 a 與 b )的方法外,其實只 要將歐幾里得演算法稍作修改,我們不難讓 求最大公因數與求解可以同時進行,使得在 求出最大公因數的同時也求得了ax+by=d 的一組解。 一開始,我們先寫下如下兩 個恆等式:a b = = 1 0 a a + + 0 1 b b ⋅ ⋅ ⋅ ⋅ 也就是將 a 和 b 分別用 a 與 b 表示,接 著就如同一般歐幾里得演算法的步驟,設法 經由兩式之間的算術運算使得等號左邊成為 a 與 b 的最大公因數;由於運算過程的每個 階段等號左邊的數都被表示成 a 與 b 的線性 組合,因此當等號左邊為 a 與 b 的最大公因 數時,自然就有了d =ax+by的一組解。 舉例來說,假設 a = 477,b = 138,我們 用下面兩個式子為起點: 477 = 1 477 + 0 138 138 = 0 477 + 1 138 (1) (2) ⋅ ⋅ ⋅ ⋅ 由(1)−3×(2)得
63
=1
⋅477
−
3
⋅138
(3)
由(2)−2×(3)得(4)
12
=−
2
⋅477
+
7
⋅138
由(3)−5×(4)得3
=11
⋅477
−
38
⋅138
(5)
等 號 左 邊 的 3 很 明 顯 是 12 的 因 數 , 因 此 3 ) 138 , 477 gcd( = ,此時由(5)式的等號右邊可 知(x, y) = (11,−38)為方程式477x+138y =3 的一組解。一個簡單的遊戲
以下是一個與最大公因數有關的遊戲, 在教室裡很容易就可以進行。首先,老師先 在黑板上寫下兩個正整數,然後請兩位同學 上台,輪流在黑板上寫下更多數字。每位同 學每次所寫的數必須是當時黑板上的某兩個 數的差(大數減去小數),而且不能與黑板上 已有的數重覆。此遊戲一直持續到有一方無 法寫出新數為止,此人就是遊戲的輸家。 如果某位參賽者有權決定遊戲是由自己 或對方開始的話,他其實一定可以贏得這場 遊戲;在往下看之前,請讀者想一想,他的 致勝之道是什麼? 假設最初由老師提供的兩數為 a 與 b 且 a 大於 b,讀者不難看出,參賽的同學所寫下 的每個數一定都是gcd( ba, )的倍數,而且隨 著遊戲的進行,所有小於 a 的gcd( ba, )的倍 數都能陸續出現在黑板上。因此,當 a 與 b 的值確定後,參賽的兩方總共會在黑板上寫 下多少個數其實就已經確定了,總共有 2 ) , gcd(a b − a 個數。因此如果某位參賽者有權決定遊戲是 由自己或對方開始的話,整場遊戲的輸贏當 然已經在他的掌握之中。結語
對任意正整數 a 與 b 而言,由於所有可 以 表 示 成ax+by的 正 整 數 一 定 是gcd( ba, ) 的倍數,因此gcd( ba, )其實是可以表示成形 如ax+by的所有正整數中最小的整數,這可 以看成是最大公因數的另一個定義。 最後我們來看這篇文章一開始小明所面 臨的問題。經由河水在桶子間的倒進倒出, 小明希望能剩下不多不少正好 6 公升的河 水;這個問題相當於在求15x+27y=6的整 數解。由於gcd(15,27)=3而 6 是 3 的倍數, 因此我們可以肯定此問題有解。首先由歐幾 里得演算法求出最大公因數:27 = 1 15 = 1 3 = 4 15 12 12 + + 12 3 ⋅ ⋅ ⋅ 再由最大公因數 3 反推回去: ⋅ 3 = 12 = = 15 − 15 − (27−15) 2 15 − 27 我 們 得 到15x+27y=3 的 一 組 解(x,y) = ) 1 , 2 ( − ,因此15x+27y=3的一般解為 ) 5 1 , 9 2 ( ) , (x y = + n− − n 而15x+27y=6的一般解為 ) 5 2 , 9 4 ( ) , (x y = + n− − n 所以,小明有無窮多種做法來解決他所 面臨的問題。以 (x,y)=(4,−2)為例,他可以 這麼做:將容量為 15 公升的桶子裝滿河水 4 次,每當裝滿了就往容量為 27 公升的桶子裡 倒,而每當容量 27 公升的桶子滿了就將桶中 的河水倒回河中;在大桶子第二次倒滿時, 小桶子中的河水將不多不少正好是 6 公升。
練習題
以下是幾個和本文相關的問題,提供讀 者參考: 1. 某人用 1000 元買了 100 隻雞。已 知雞分成 三種,公雞每隻 50 元,母雞每隻 30 元, 而小雞每三隻才 10 元。請問此人總共買了 公雞、母雞、小雞各幾隻?(請列出所有 可能的組合) 2. 小明和小華都剛找到工作,今天是他們上 班的第一天。小明每上班三天就會休息一 天,小華每上班七天就會休息三天。在未 來的 1000 天中,有多少天他們兩人同時都 不上班? 3. 對任意兩個正整數 a 與 b 而言,如果a x + by = 2 有整數解,是否ax2 +by2 =2也一定有 整數解? 4. 在 所 有 小 於 2002 的 正 整 數 中 , 會 使 得 ) 4 /( ) 7 (n2 + n+ 不是最 簡 分 數 的 正 整 數 n 有幾個?參考資料
1. 許介彥(2001), 遞迴演算法簡介, 科學教 育月刊, 第 245 期。2. Donald E. Knuth, The Art of Computer Programming , Vol. 1, 3rd edition, Addison- Wesley, 1997.
3. Kenneth H. Rosen, Discrete Mathematics and Its Applications, 4th edition, McGraw- Hill, 1999.