欧几里得算法及其扩展
欧几里得算法及其扩展
前言
整除:对于整数
最大公约数
公约数:如果一个整数是集合中任意一个元素的约数,则这个整数是该集合中的最大公约数。
最大公约数:集合的公约数中最大的一个,通常用
最大公约数经典的算法有:欧几里得算法(辗转相除法)、更相减损术。
欧几里得算法
“欧几里得算法”又名“辗转相除法”
过程
已知两个正整数
若
若
“辗转相除法”与“更相减损术”都基于事实:
当
时, ,其中 为正整数。
当取最大值 ,又可以写成 证明:
设
与 的最大公约数是 ,则 使得 由于
是最大公约数,所以 与 中不存在大于 的公约数,即 与 互质 现在要证:
也是 与 的最大公约数
即证与 互质 假设
与 不互质,它们的最大公约数为 ,则
此时
与 不互质,与已证条件不符,因此 与 互质 证毕
实现
/**
* 通过递归实现的欧几里得算法求解最大公约数
* @param a 一个正整数
* @param b 一个正整数
* @return a与b的最大公约数
*/
int gcd(int a, int b) {
int rest = a % b;
if (rest == 0) {
return b;
}
return gcd(b, rest);
}
可以写成迭代的形式
/**
* 通过迭代实现的欧几里得算法求解最大公约数
*
* @param a 一个正整数
* @param b 一个正整数
* @return a与b的最大公约数
*/
int gcd(int a, int b) {
if (a < b) {
return gcd(b, a);
}
while (true) {
int rest = a % b;
if (rest == 0) {
return b;
}
a = b;
b = rest;
}
}
最小公倍数
公倍数:如果一个整数能被集合中任意一个数整除,则这个整数是该集合的公倍数。
最小公倍数:集合的公倍数中最小的一个,通常用
对于正整数
则由最大公约数与最小公倍数的定义得:
由于
所以
所以
扩展欧几里得算法
常用于求
过程
- 欧几里得定理
, 代入 , 带入- 正整数取模定义,
- 合并同类项
因此,
对比系数得:
当
作为人类,通常会选择令最后一层的
因为
再从下至上递归求出 最开始的
此时可以得到方程的通解为
若要求得
值域分析
由于
若
实现
int x = 0, y = 0;
int exgcd(int a, int b) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int gcd = exgcd(b, a % b), t = x;
x = y;
y = t - a / b * y;
return gcd;
}
迭代方法
欧几里得算法可以通过迭代的方式求得最大公约数,那扩展欧几里得是否也能迭代呢?
答案是肯定的。
若
初始情况,当
由
接下来
int x = 0, y = 0;
int exgcd(int a, int b) {
x = 1;
y = 0;
int nx = 0, ny = 1, q, t;
while (b != 0) {
q = a / b;
x -= q * nx;
t = x; x = nx; nx = t;
y -= q * ny;
t = y; y = ny; ny = t;
a -= q * b;
t = b; b = a; a = t;
}
// 结束后
// a 是 gcd(a,b)
// 如果 gcd(a,b)!=1 则 无整数解
// 否则 x,y 是 ax+by=gcd(a,b) 的一组整数解
return a;
}
int x, y;
int exgcd(int a, int b) {
x = 1, y = 0;
int nx = 0, ny = 1, q;
while (b != 0) {
q = a / b;
std::swap(x -= q * nx, nx);
std::swap(y -= q * ny, ny);
std::swap(a -= q * b, b);
}
// 结束后
// a 是 gcd(a,b)
// 如果 gcd(a,b)!=1 则 无整数解
// 否则 x,y 是 ax+by=gcd(a,b) 的一组整数解
return a;
}
二元一次不定方程
关于
裴蜀定理
对于
证明(By other):
首先,显然有
, 。由整除的性质可知 。设 为 的最小正值,故有 。
设,则有 ,发现 也为 的线性组合,而 又在模 剩余系中,故 ,又由于 为最小正值,故 。
所以,同理 ,根据两个数的公约数必为这两个数的最大公约数的约数,有 ,而上文已证明 ,故 。
进而得证,故这个方程一定有解
判断方程有整数解的条件
方程
证明(By other):
考虑将
变为
为了区分这两个方程,我们将前者改为
令,方程两边同除 ,得: 方程两边同乘c得:
只要通过换元,即令
,即可将方程转化为 的形式
考虑到,且对于一般的方程:
故只有为 倍数时原方程有解,即 ,从而得证。
求解二元一次不定方程
对于解方程
当我们得到了
两边同时除以
则
此时可以得到方程的通解为
若要求得
线性同余方程
关于
与 二元一次不定方程 等价
对于方程
证明:
- 同余号转等号
- 取模定义
- 合并同类项
求解线性同余方程
转化为 二元一次不定方程,求解该不定方程,即是求解线性同余方程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)