【知识】 扩展欧几里得算法
前言
扩展欧几里得算法是一个常用的数论算法,可以用于求解不定方程、线性同余方程、模意义下的乘法逆元等。网上很多资料对于代码的关键部分证明十分模糊,这篇文章带你完全理解扩展欧几里得算法。
回顾普通欧几里得算法
大部分人初学算法肯定会接触到求最大公约数的欧几里得算法,它也叫做 「辗转相除法」。
它的求解过程十分简单:
1 | int gcd(int a, int b) { |
原理也可以用小学二年级知识理解:假设
刚才的过程中我们用到了欧几里得定理,即
由此我们还可以得出每一层递归时的
历史资料
欧几里得算法,又称辗转相除法,被认为是世界上最早的算法(公元前
在中国,东汉出现的 《九章算术》 中介绍了一种与欧几里得算法的弱化版 「更相减损法」,其实就是把取模换成了一点一点地减。
扩展欧几里得算法
首先我们需要知道 「裴蜀定理」:对于任意
裴蜀定理的一个推论是,不定方程
于是我们可以通过这种方法来判断不定方程
但人类仍不知足……我还想知道在
注意:扩展欧几里得算法算法只能解
它的实现方法是在普通欧几里得算法递归求
计算
详细计算方法请看下面代码详解(保证对每一句话都做详细解释):
1 | int exgcd(int a, int b, int &x, int &y) { // 这里x和y都要被修改,所以使用引用参数 |
其实我们可以发现,如果我们只要求 void
类型。
对于 x = y, y = t - a / b * y;
这个计算,我第一次看到的时候也觉得十分神秘,为什么这样推出来的
重点来了!!!接下来的证明网上很多自称 「超详解」 的教程都没讲或糊弄一下就过去了。过程并不复杂,大概只有初中知识,长点脑子的应该都能看懂。
设当前层要求的
则
由欧几里得定理可知:
故
又因为
将其代入
展开得
即
又因为
且注意到
故
以上证明过程来自 OI Wiki 扩展欧几里得算法 ,稍有改动。
然后我们的 x = y, y = t - a / b * y;
就出来啦!是不是觉得很神奇!
最后我们要求不定方程
1 | int x, y; // 因为是引用参数,所以x和y需要单独开变量 |
- 标题: 【知识】 扩展欧几里得算法
- 作者: Xlon WU
- 创建于 : 2024-09-24 14:55:43
- 更新于 : 2024-11-01 16:43:16
- 链接: https://xlon-wu.top/2024/09/24/exgcd/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。