# 拡張ユークリッドの互除法 (拡張されたユークリッドの互除法) ## 定義 > $x, y$ を $0$ でない自然数とし、 $c = \mathrm{GCD}(x,y)$ とする。このとき > > $ > ax + by = c > $ > > となる整数 $a,b$ が存在する。そして、この $a,b$ は実際に計算することが出来る。 ## ユークリッドの互除法から [[ユークリッドの互除法]] からの導出 $ \begin{align} &\mathrm{GCG}(13, 5) \\ \\ 13 &= 2 \times 5 + 3 \tag{1} \\ 5 &= 1 \times 3 + 2 \tag{2} \\ 3 &= 2 + 1 \tag{3} \\ 2 &= 2 \times 1 \\ \\ &\mathrm{CCG}(13, 5) = 1 \end{align} $ $(1),(2),(3)$ を移項 $ \begin{align} 13 - 2 \times 5 &= 3 \tag{4} \\ 5 - 1 \times 3 &= 2 \tag{5} \\ 3 - 1 \times 2 &= 1 \tag{6} \end{align} $ $(5)$ を $(6)$ に代入 $ \begin{align} 1 &= 3 - 1 \times 2 \\ 1 &= 3 - 1 \times (5 - 1 \times 3) \\ 1 &= 2 \times 3 - 1 \times 5 \tag{7} \end{align} $ $(4)$ を $(7)$ に代入。 13 と 5 に注目してくくる $ \begin{align} 1 &= 2 \times 3 - 1 \times 5 \\ 1 &= 2 \times (13 - 2 \times 5) - 1 \times 5 \\ 1 &= 2 \times 13 - 5 \times 5 \end{align} $ $ 2 \times 13 - 5 \times 5 = 1 $ (13 リットルの升と 5 リットルの升を使って 1 リットルを測ることができる) 定式化すると、冒頭の拡張ユークリッド互除法になる。 ## Go による実装 ### 再帰 ver ```go package main import "fmt" // ax + by = GCD(a, b) func extGCD(a, b int) (int, int, int) { if b == 0 { return a, 1, 0 } gcd, x1, y1 := extGCD(b, a%b) x := y1 y := x1 - (a/b)*y1 return gcd, x, y } func main() { a := 119 b := 544 gcd, x, y := extGCD(a, b) fmt.Printf("GCD: %d, x: %d, y: %d\n", gcd, x, y) } ``` ### 非再帰 ver 「[[mod 逆元を求める]]」のコードを参照。 ### 逆元を求める [[mod 逆元を求める]] ```go func main() { for i := 1; i < 13; i++ { _, x, _ := extGCD(i, 13) if x < 0 { x += 13 } fmt.Printf("%2d => %2d\n", i, x) } } ```