# 拡張ユークリッドの互除法
## 拡張ユークリッドの互除法とは?
拡張ユークリッドの互除法とは、競技プログラミングでも用いられるアルゴリズムで、次の方程式の解 $(x, y)$ を求めることができる。
$$
\begin{equation} ax + by = c \tag{1}
\end{equation}
$$
アルゴリズムの説明の前に、上の方程式について少し考えてみよう。
自然数 $a, b, c$ が与えられたとき、方程式 $(1)$ に整数解 $(x, y)$ が存在するのはどのような場合なのだろうか?
いくつか具体例を考えてみる。 $a = 10, b = 4, c = 2$ のとき、方程式 $10x + 4y = 2$ は解 $x = -1, y = 3$ を持つ。しかし、 $a = 10, b = 4, c = 1$ のとき、方程式 $10x + 4y = 1$ は整数解 $(x, y)$ を持たない。
実は、方程式 $(1)$ に整数解が存在する条件は $c$ が、 $a$ と $b$ の最大公約数 $g$ の倍数になることである。実際、 $ax + by$ は $g$ の倍数となるため、解が存在するには $c$ が $g$ の倍数にならなければならないことがわかる。
## 拡張ユークリッドの互除法のアルゴリズム
ここから拡張ユークリッドのアルゴリズムについて述べる。
拡張ユークリッドの互除法アルゴリズムは、 自然数 $a, b$ が入力されたとき、
$$
\begin{equation}
ax + by = g \tag{2}
\end{equation}
$$ の整数解 $(x, y)$ を返すものである。
このアルゴリズムにはユークリッドの互除法に似たアイデアが使われている。
$a = q \cdot b + r$ と整数 $q, r\; (r < b)$ を用いて表せるので、
$ax + by = (qb + r)x + by = b(qx + y) + rx$ となる。よって、$x' = qx + y,\: y' = x$ とおくと、
$$
\begin{equation}
bx' + ry' = g \tag{3}
\end{equation}
$$ と $ax + by = g$ に似た形の方程式が得られた。よって、方程式 $(3)$ の整数解 $(x', y')$ が得られれば、それを $x' = qx + y,\: y' = x$ つまり $x = y',\: y = x' - qy'$ に代入することで $ax + by = g$ の整数解 $(x, y)$ が得られる。
方程式 $(3)$ の整数解は常に存在するだろうか? 実はこれは常に存在する。なぜなら、最大公約数の性質から $gcd(a, b) = gcd(b, r)$ であり、前に行った方程式 $(1)$ の存在についての議論から方程式 $(3)$ は整数解を持つからである。
方程式 $(2)$ から $(3)$ へ変換することで、 $b$ と $r$ というより小さなサイズの問題に帰着できるのである。また、この変換をユークリッドの互除法と同じように繰り返すことで、いずれ
$$
\begin{equation}
gx + 0 \cdot y = g
\end{equation}
$$ という形の方程式が得られる。この方程式の整数解は $(1, 0)$ と簡単に求められる。あとはこの解から1つ前の方程式の解を求めて... とやっていけばいずれ求めたかった、方程式 $(2)$ の整数解が得られる。これが拡張ユークリッドの互除法のアルゴリズムである。
## アルゴリズムを具体例に適用してみる
具体例として$a = 10,\: b = 4$ に対してアルゴリズムを適用して $10x + 4y = 2$ の整数解を求めてみる。
$$
\begin{align}
10x + 4y &= 2 \\
4(2x + y) + 2x &= 2 \\
4x' + 2y' &= 2 \\
2(2x' + y') + 0 \cdot x' &= 2 \\
2x'' + 0 \cdot y'' &= 2
\end{align}
$$
となる。ただし、$x' = 2x + y,\: y' = x,\: x'' = 2x' + y',\: y'' = x'$ とおいた。
$x'' = 1,\: y'' = 0$ より、$x' = 0,\: y' = 1$ が得られ、これを使って求めたかった解 $x = 1,\: y = -2$ が得られる。
## アルゴリズムの実装例
最後に、拡張ユークリッドの互除法アルゴリズムのPythonでの実装例を紹介する
```
def extendedGCD(a, b):
if b == 0:
return (1, 0)
q = a // b
r = a % b
x, y = extendedGCD(b, r)
return (y, x - q*y)
```