# mod 逆元を求める
[モジュラ逆数 - Wikipedia](https://ja.wikipedia.org/wiki/モジュラ逆数)
どちらも $O(\log m)$
- [[フェルマーの小定理]]
- 実装がわかりやすい
- 法 $m$ が素数でないと使えない
- [[拡張ユークリッドの互除法]]
- 法 $m$ が素数でなくても使える
- 正し、逆元の存在条件を満たすこと
- $\mod m$ での $a$ の逆元が存在する条件は、 $m$ と $a$ が互いに素であること
## 拡張ユークリッドの互除法の利用
### 原理
$
\begin{align}
n \times n^{-1} &= 1 \pmod m \\
n \times n^{-1} -1 &= 0 \pmod m
\end{align}
$
左辺は $m$ で割り切れる。
$q$ を適当な整数とする。
$
\begin{align}
n \times n^{-1} - 1 &= m \times q \\
n \times n^{-1} + m \times (-q) &= 1 \tag{1}
\end{align}
$
拡張ユークリッドの互助法の式は
$
a \times x + b \times y = \mathrm{GCD}(a,b)
$
( $(x,y)$ を同時に求められる)
これに当てはめると
$
a \times a^{-1} + m \times q = \mathrm{GCD}(a,m) \tag{2}
$
$a$ と $m$ が互いに素であれば、$(1)$ と $(2)$ が同じ形になる。
(逆元 $a^{-1}$ を求めたいだけなので、 $q$ は不要)
## Go による実装
### 非再帰 ver
```go
// 法 m での a の逆元を求める関数
func modInv(a int, m int) int {
var b, u, v = m, 1, 0
for b != 0 {
t := a / b
a -= t * b
a, b = b, a
u -= t * v
u, v = v, u
}
u %= m
if u < 0 {
u += m
}
return u
}
```
`u` と `v` は、以下の $u$ と $v$
[ユークリッドの互除法#拡張された互除法 - Wikipedia](https://ja.wikipedia.org/wiki/ユークリッドの互除法#拡張された互除法)
$
\begin{aligned}
\begin{pmatrix}
x & y \\
u & v \\
\end{pmatrix}
=
\begin{pmatrix}
0 & 1 \\
1 & -k_{h - 1} \\
\end{pmatrix}
\begin{pmatrix}
0 & 1 \\
1 & -k_{h - 2} \\
\end{pmatrix}
\cdots
\begin{pmatrix}
0 & 1 \\
1 & -k_{2} \\
\end{pmatrix}
\begin{pmatrix}
0 & 1 \\
1 & -k_{1} \\
\end{pmatrix}
\begin{pmatrix}
0 & 1 \\
1 & -k_{0} \\
\end{pmatrix}
\end{aligned}
$
### 再帰 ver
「[[拡張ユークリッドの互除法]]」を参照。