辗转相除法证明了解一下

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

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 参考

<think>好的,用户想了解如何用辗转相除法求最大公约数的算法实现。首先,我需要回顾一下辗转相除法的基本原理,确保自己理解正确。根据引用[2]和[3],辗转相除法是通过反复用较大的数除以较小的数,然后用余数替换较大的数,直到余数为零,此时的除数就是最大公约数。 接下来,用户需要具体的算法实现步骤。我应该分步骤解释,从算法描述到代码实现。可能需要用例子来说明,比如计算252和105的最大公约数。这样用户能更直观地理解过程。 然后,代码实现部分,用户可能希望看到不同编程语言的例子,但问题中没有明确指定。不过根据引用[1]和[4],用户提到了C语言和Python,所以最好提供这两种语言的代码示例,这样覆盖更多用户的需求。需要确保代码正确,比如递归和迭代两种方法,这样用户可以选择他们习惯的方式。 另外,用户可能对时间复杂度和应用场景感兴趣,虽然问题主要关注实现,但简要提及这些可以增加回答的全面性。比如引用[3]提到的定理,可以解释为什么算法有效,增强说服力。 还需要检查是否有常见的错误注意事项,比如处理输入为零的情况,者确保输入是非负整数。这些细节能帮助用户写出更健壮的代码。 最后,生成相关问题时要围绕算法的原理、实现细节、优化和应用等方面,帮助用户进一步学习。比如询问原理的证明、优化方法、其他算法比较等。 总结步骤:先解释算法步骤,用例子演示,提供多语言代码,分析复杂度,注意事项,最后相关问题。需要确保使用正确的LaTeX格式,行内公式用$...$,独立公式用$$...$$,并正确引用参考资料。</think>### 辗转相除法求最大公约数(算法实现) #### 一、算法原理 辗转相除法基于以下定理: **若 $a \div b = q \cdots r$,则 $\gcd(a, b) = \gcd(b, r)$**[^3]。 通过反复用除数替换被除数、余数替换除数,直到余数为0时,当前除数即为最大公约数[^2]。 #### 二、算法步骤 1. 输入两个非负整数 $a$ 和 $b$(要求 $a \geq b$,否则交换两者) 2. 计算 $a \div b$ 的余数 $r$ 3. 若 $r = 0$,则 $b$ 是最大公约数 4. 若 $r \neq 0$,令 $a = b$, $b = r$,重复步骤2-3 #### 三、示例演示(以 $\gcd(252, 105)$ 为例) 1. $252 \div 105 = 2 \cdots 42$ 2. $105 \div 42 = 2 \cdots 21$ 3. $42 \div 21 = 2 \cdots 0$ 最终 $\gcd(252, 105) = 21$ #### 四、代码实现 **C语言(递归版本):** ```c int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); } ``` **Python(迭代版本):** ```python def gcd(a, b): while b != 0: a, b = b, a % b return a ``` #### 五、算法特性 - **时间复杂度**:$O(\log(\min(a, b)))$,效率极高 - **空间复杂度**:迭代版本 $O(1)$,递归版本 $O(\log n)$ - **关键操作**:取模运算(`%`) #### 六、注意事项 1. 必须确保输入为非负整数(若含负数,需先取绝对值) 2. 当输入包含0时,$\gcd(a, 0) = |a|$ 3. 递归实现需注意栈溢出风险(建议优先使用迭代版本)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值