辗转相除法证明了解一下

2,272 阅读2分钟

写在前面:本着弄懂每一个小知识点的学习原则,打算彻底理清一下辗转相除法。

1 什么是辗转相除法?

辗转相除法,又称欧几里得算法……

2 为什么辗转相除可以求解最大公约数?

可能我们会凭记忆使用这个简单的算法,但是如果我们多问自己一个为什么?思路就有点模糊了,可能会想:“是啊,为什么呢?难道又是玄学?”。下面就给出一系列疑问的证明:

首先我们给定两个数 a, b 并且约定 a \ge b > 0

如果 a\%b = 0,则 gcd(a, b) = b
如果 a\%b \neq 0,则设 a = n*b + m
根据辗转相除法,我们可以得出 gcd(a, b) = gcd(b, a\%b) 疑问就在这里,等式为什么成立?我们拆分为两个子问题:

Q1: gcd(a, b)(b, a\%b) 的一个公约数,其中 a\%b = m

因为:

a = k_1 * gcd(a, b) \\\\
b = k_2 * gcd(a, b)

所以:

a\%b = m = a - n * b = (k_1 - n * k_2)gcd(a, b)

由于 (k_1 - n * k_2) 是正整数,所以 gcd(a, b)(b, a\%b) 的一个公约数。

Q2: 如何证明 gcd(a, b) 就是 gcd(b, a\%b),换就话说如何证明是“最大”公约数?

我们来重新审视一下条件:

\begin{aligned}
b &= k_2 * gcd(a, b) \\\\
a\%b = m = a - n * b &= (k_1 - n * k_2) * gcd(a, b)
\end{aligned}

要想证明 gcd(a, b)gcd(b, a\%b),也就是说证明 k_2, (k_1 - n * k_2) 互质,即 gcd(k_2, k_1 - n * k_2) = 1

由于 n 是正整数,不好直接证明,那么我们取特殊的当 n = 1 时到底是否成立?即 gcd(k_2, k_1 - k_2) = 1。如果你对数论有点了解可能立马就知道 gcd(num1, num2) = gcd(num1, num1 - num2),又因为 gcd(k_1, k_2) = 1 所以得证;如果你不知道也没关系,我们可以证明,毕竟我们就是来搞懂一个个细节的。

因为:

a = k_1 * gcd(a, b) \\\\
b = k_2 * gcd(a, b)

所以:

gcd(k_1, k_2) = 1

k_1, k_2 互质的情况下,k_1 - k_2 不可能含有数值为 k_1k_2 因子。 否则 gcd(k_1, k_2) \neq 1

所以结论 gcd(k_2, k_1 - k_2) = 1 得证。 继续使用这个结论可以得出:

\begin{aligned}
1 &= gcd(k_2, k_1 - k_2) \\\\
&= gcd(k_2, k_1 - k_2 - k_2) \\\\
&= \ldots \\\\
&= gcd(k_2, k_1 - n * k_2)
\end{aligned}

所以有:

gcd(a, b) = gcd(b, a\%b)

然后一直迭代就可以啦!

如果里面有什么错误欢迎指出来,可以一起探讨。

3 如何高效实现?

请参考漫画算法:辗转相除法是什么鬼?

4 参考