欧几里得算法
用于求解两个数 a,b 的最大公约数,gcd(a,b)=gcd(b,amodb),为了方便证明,我们约定 a>b,证明:
设 r=amodb=a−k⋅b,d∣a 且 d∣b,显然 a=k⋅b+r,那么 rd=ad−k⋅bd,因为 ad−k⋅bd 显然为整数,所以 rd 也为整数,所以可证 gcd(a,b)=gcd(b,amodb)。□
所以我们就可以写出如下代码:
Link
il int gcd(int a,int b) {
return b ? gcd(b,a % b) : a;
}
因为每次进行取模再递归,所以时间复杂度为 O(loga)。
扩展欧几里得算法
用于求 ax+by=gcd(a,b) 的一组可行解。
前置知识:裴蜀定理:对于任意整数 a,b,存在一对整数 x,y,满足 ax+by=gcd(a,b)。
推导:
由欧几里得算法,可得 ax1+by1=gcd(a,b) 等同于 bx2+(amodb)y2=gcd(b,amodb)。
所以 ax1+by1=bx2+(amodb)y2,将 amodb 转换,得到 ax1+by1=bx2+(a−⌊ab⌋⋅b)y2。
把式子拆开 ax1+by1=bx2+ay2−⌊ab⌋⋅b⋅y2,
合并 ax1+by1=ay2+b⋅(x2−⌊ab⌋⋅y2),
得到 x1=y2,y1=(x2−⌊ab⌋⋅y2),那么我们就可以根据这个,不断递归求解,当递归到 b=0 时,返回 a 的值即可,为了方便操作,可以将 x,y 取地址。
可以写出如下代码:
Link
il int exgcd(int a,int b,int &x,int &y) {
if (!b) {
x = 1; y = 0;
return a;
}
int d = exgcd(b,a % b,y,x);
y -= a / b * x;
return d;
}
一般的,对于 ax+by=c,我们可以知道,该方程有整数解当且仅当 gcd(a,b)∣c。
此时我们可以优先求解 ax′+by′=gcd(a,b),令 d=gcd(a,b),我们可以得到方程的通解为
⎧⎪
⎪⎨⎪
⎪⎩x=x′×cd+bd⋅ky=y′×cd−ad⋅k
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律