如果你觉得现存的Exgcd讲解说的都不是人话,就来看这篇吧
非常重要的推广的欧几里德算法也称 exgcd,可以解决这样一个问题:
求出整数
m
′
m'
m′和
n
′
n'
n′使得下列式子(方程)成立
m
′
m
+
n
′
n
=
g
c
d
(
m
,
n
)
(
4.5
)
m'm+n'n=gcd(m,n)\quad \quad (4.5)
m′m+n′n=gcd(m,n)(4.5)
Concrete Math原文讲解是这样的:
做法是如果
m
=
0
m=0
m=0,我们直接取
m
′
=
0
m'=0
m′=0 以及
n
′
=
1
n'=1
n′=1,
反之就令
r
=
n
m
o
d
m
r=n\ mod\ m
r=n mod m并用
r
r
r 和
m
m
m 替换
m
m
m 和
n
n
n再次应用这一方法来计算
r
‾
\overline{r}
r 和
m
‾
\overline{m}
m 使得
r
‾
r
+
m
‾
m
=
g
c
d
(
r
,
m
)
.
.
.
.
.
.
\overline{r}r+\overline{m}m=gcd(r,m)......
rr+mm=gcd(r,m)......
不太容易阅读,因为实在不理解这是个什么东西,这里一个很好的理解的方式就是左边其实就是 m m m 和 n n n 的一个线性组合,生成了他们的最大公因数 g c d ( m , n ) gcd(m,n) gcd(m,n),那么这个算法就是用于求得线性组合生成他们的 g c d gcd gcd 所需的系数 m ′ m' m′和 n ′ n' n′ 那么 m ′ m' m′ 取 0 0 0 的做法就很容易理解了,因为 0 0 0和任意数 n n n的 g c d gcd gcd都为 n n n,为了生成 g c d ( m , n ) gcd(m,n) gcd(m,n)也就是 n n n ,那么我们只需 1 1 1 个 n n n 和 0 0 0 个 m m m 就可以得到了。
都不为 0 0 0 的情况我们找到什么样的 m ′ m' m′ 和 n ′ n' n′ 才能生成它们的 g c d gcd gcd 呢,这个问题直接寻找答案 困难,但是我们可以用欧几里德算法给出的规律将这个问题演化,变得与第一种情况有关,就可以进行方便的求解了。
用 ( n m o d m , m ) (n\ mod\ m,m) (n mod m,m) 来替换 ( m , n ) (m,n) (m,n) 二元组,核心和欧几里德算法是一样的,由欧几里德算法的规律,我们得到的等式的右边 g c d gcd gcd 是不变的,我们令 n m o d m n\ mod\ m n mod m 为 r r r ,尝试计算更小规模的一个问题, r ‾ r + m ‾ m = g c d ( r , m ) \overline{r}r+\overline{m}m=gcd(r,m) rr+mm=gcd(r,m) (由于有一个参数被另一个参数取模了,所以规模更小)
这里补充一个mod定义
m
m
o
d
n
=
m
−
⌊
m
/
n
⌋
×
n
m\ mod\ n=m-\lfloor m/n\rfloor\times n
m mod n=m−⌊m/n⌋×n
很好理解,
m
m
m 减掉了能够减掉的最大次数的
n
n
n (再多减一次就就会变成负数),而这个最大次数就是
m
/
n
m/n
m/n 去掉多余的小数
这个规模更小的问题问题实际上就是
r
‾
(
n
−
⌊
n
/
m
⌋
m
)
+
m
‾
m
=
g
c
d
(
r
,
m
)
\overline{r}(n-\lfloor n/m\rfloor m)+\overline{m}m=gcd(r,m)
r(n−⌊n/m⌋m)+mm=gcd(r,m)
也就是
r
‾
(
n
−
⌊
n
/
m
⌋
m
)
+
m
‾
m
=
g
c
d
(
m
,
n
)
\overline{r}(n-\lfloor n/m\rfloor m)+\overline{m}m=gcd(m,n)
r(n−⌊n/m⌋m)+mm=gcd(m,n)
展开后我们得到
r
‾
n
−
r
‾
⌊
n
/
m
⌋
m
+
m
‾
m
=
g
c
d
(
m
,
n
)
\overline{r}n-\overline{r}\lfloor n/m\rfloor m+\overline{m}m=gcd(m,n)
rn−r⌊n/m⌋m+mm=gcd(m,n)
我们再改写式子尝试找到与原问题的关系:
(
m
‾
−
⌊
n
/
m
⌋
r
‾
)
m
+
r
‾
n
=
g
c
d
(
m
,
n
)
(\overline{m}-\lfloor n/m\rfloor\overline{r})m+\overline{r}n=gcd(m,n)
(m−⌊n/m⌋r)m+rn=gcd(m,n)
我们发现
m
m
m 和
n
n
n 前面的系数正好分别就是我们要找的
m
′
m'
m′ 和
n
′
n'
n′
假设我们可以找到规模小一些的这个问题的答案,也就是我们可以找到 r ‾ \overline{r} r 和 m ‾ \overline{m} m 使得 r ‾ r + m ‾ m = g c d ( r , m ) \overline{r}r+\overline{m}m=gcd(r,m) rr+mm=gcd(r,m) 那么原问题的系数 ( m ‾ − ⌊ n / m ⌋ r ‾ ) (\overline{m}-\lfloor n/m\rfloor\overline{r}) (m−⌊n/m⌋r) 和 r ‾ \overline{r} r 就可以很快速的搞定了。
要解决大问题,就要解决小一点的问题,要解决小一点的问题,就要解决更小一点的问题,直到这个问题的规模可以小到 m m m 或 n n n 的值为 0 0 0变成了第一种边界情况。这个问题就得以解决了。复杂度与欧几里德算法相似,为 O ( l o g n ) O(log\ n) O(log n)