Loading [MathJax]/jax/output/CommonHTML/jax.js

アルゴリズム論特論(塩田)第3回 (4) 拡張ユークリッドアルゴリズム

拡張ユークリッドアルゴリズム

 ユークリッドのアルゴリズムを改良して
ax+by=gcd(a,b)
を満たす x, y も求めましょう。
Algorithm 9 (拡張ユークリッドアルゴリズム)
  • 入力:a, b
  • 出力:d=gcd(a,b) と、ax+by=gcd(a,b) を満たす x, y
  1. 3つの数列 {rn}, {xn}, {yn} を宣言する
  2. r0a, r1b, x01, x10, y00, y11, n0 とおく
  3. rn+1=0 ならば 5° へ
  4. q(rn÷rn+1 の商 ),
    rn+2rnq×rn+1,
    xn+2xnq×xn+1,
    yn+2ynq×yn+1,
    nn+1 として 3° へ
  5. rn<0 ならば (rn,xn,yn)(rn,xn,yn),
  6. (d,x,y)=(rn,xn,yn) を出力
証明 {rn}Alg.6 と同じものなので、 出力の dgcd(a,b) であることと、 有限回のステップで終了することは証明できています。 あとは、全ての番号 n について
rn=axn+byn
が成り立つことを帰納法で示します。
 n=0, 1 のときは、初期値設定から
r0=a=a×1+b×0=ax0+by0,
r1=b=a×0+b×1=ax1+by1
となって成り立っています。n, n+1 のとき正しければ
rn+2=rnq×rn+1
=(axn+byn)q×(axn+1+byn+1)
=a(xnq×xn+1)+b(ynq×yn+1)
=axn+2+byn+2.
(証明終)

実行例

Ex.10 13579x+2468y=1 を満たす x, y は?
n q rn xn yn
0 13579 1 0
1 2468 0 1
25=13579/2468 1239 1 5
31=2468/1239 1229 1 6
41=1239/1229 10 2 11
5122=1229/10 9 245 1348
61=10/9 1 2471359
79=9/1 0
rn0 になる直前の行から
gcd(13579,2468)=1=13579×247+2468×(1359).
( 表の作り方:
r2=r05×r1=135795×2468=1239
に合わせて
x2=x05×x1=15×0=10
y2=y05×y1=05×1=5
のように計算します。)
Ex.10' 13579x+2468y=1 を満たす x, y を、負の余りも使うパターンでも計算してみましょう。
n q rnxn yn
0 13579 1 0
1 2468 0 1
26=round(13579/2468)1229 1 6
32=round(2468/(1229)) 10 2 13
4123=round((1229)/10) 12471359
510=round(10/1) 0
rn0 になる直前の行から
gcd(13579,2468)=1=13579×247+2468×(1359).
プログラミング上の注意
  • 数列 {rn}, {xn}, {yn} はいずれも直前の 2 項しか残す必要が無いので、変数を使い回せば配列を使わなくて済みます。
  • yy=(gcd(a,b)ax)/b によって計算できるので、必ずしも {yn} を計算しなくて済みます。
  • 整数商は、Python 2 では / でも // でもOKですが、Python 3 では // と書いてください。 Python3 で / を使うと実数値での計算結果が返されてしまいます。