前言
本文通过尽量短,通俗易懂的形式帮助大家理解最简单的 exgcd。
前置知识:
裴蜀定理:
ax+by=c,x∈Z∗,y∈Z∗有解的充要条件是gcd(a,b)|c
欧几里得算法(辗转相除法)
gcd(a,b)=gcd(b,amodb) (b≠0)
模运算的本质:
amodb=a−⌊ab⌋b
其中 ⌊ab⌋ 指的是 ab 下取整。
正片:
exgcd,扩展欧几里得,扩欧,是求下面这个不定方程解的方法:
ax+by=gcd(a,b)
把后面的 gcd(a,b) 辗转相除一下再写成类似的形式(这里的 x′,y′ 是对应 gcd(b,amodb) 的 x,y,和上面的 x,y 没有关系):
bx′+(amodb)y′=gcd(b,amodb)
ax+by=gcd(a,b)=gcd(b,amodb)=bx′+(a−⌊ab⌋b)y′
ax+by=bx′+(a−⌊ab⌋b)y′
因为要求解 x,y,所以假设我们已经求解了 x′,y′,则要按 a,b 把两个方程分开,然后就可以递归求解了。(貌似没有为什么,就是这么处理然后是可以递归求解的)
ax+by=ay′+b(x′−⌊ab⌋y′)
解出 x,y 就要求解 x′y′,注意求解 x′y′ 的时候,他们对应的 a,b 实际上是原先 x,y 的 a,b 的 b,amodb。
递归就能求出 ax+by=gcd(a,b) 一组特解了,最后当 b=0 的时候递归终止,此时 ax+by=gcd(a,b) 的解显然是 x=1,y=0 ( 0 和非零数的 gcd 仍为那个数本身)。
扩展欧几里得算法得到的特解一定有 |x|≤a,|y|≤b。
设解出的特解为 x0,y0,则通解为 x0+bdt,y0−adt,d=gcd(a,b)。
Code
void exgcd(int a, int b, int &x, int &y) {
if(!b) { x = 1, y = 0; return ; }
exgcd(b, a % b, x, y);
int nx = y, ny = x - (a / b) * y;
x = nx, y = ny;
}
后记
这样最基础的 exgcd 就到这里了,如果想进一步理解更深层的 exgcd,推荐阅读:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?