扩展欧几里得算法(ExGCD)

瞎扯

ExGCD用于求解不定方程

ax+by=c

的一组特解。常用于求解同余方程,比如求模非质数意义下的逆元。

推导

主体

首先,不定方程有解的充分必要条件由裴蜀定理给出

gcd(a,b)|c

于是,我们只需关注

ax+by=gcd(a,b)

的解。(原方程的解只需分别对xy乘上cgcd(a,b)即可求出)

(下文中%代指取模操作)

考虑递归的求解。假设我们已经知道了不定方程

bx+(a%b)y=gcd(b,a%b)

的解x1y1,即

bx1+(a%b)y1=gcd(b,a%b)

现在尝试利用此式构造出原方程的解xy

gcd(a,b)=gcd(b,a%b) 以及 a%b=aabb

原式化为

bx1+(aabb)y1=gcd(a,b)

拆开括号

bx1+ay1abby1=gcd(a,b)

我们的目标是构造出系数为ab的原方程,故整理得

ay1+b(x1aby1)=gcd(a,b)

成功构造。故

x=y1y=x1aby1

该递归的边界条件同欧几里得算法,当b=0时,方程为

ax=gcd(a,0)=a

x=1y=0即该方程的一组特解。

构造最小x的特解

Exgcd常用于逆元求解。这时需要找到一组解,使得x最小(正整数范围内)。可以这样构造。

我们知道,不定方程的通解形式为

{x=x0+kty=y0ku

其中,t=b/gcd(a,b),u=a/gcd(a,b)

upd:友情提示一下大家通常了解到的通解形式里面的t=b,u=a,但是实际上该通解形式仅在gcd(a,b)=1时正确(不过如果你没有意识到这一点也没啥问题,因为仍然能求出MOD内的逆元,,,)

所以,以x为例,最小的正整数x=(x0%t+t)%t,然后将其带入不定方程解出y=caxb即可。

Code

namespace ExGcd{
ll x,y;
ll ExGcd(ll a,ll b){
ll ans;
if(b==0){
x=1;y=0;ans=a;
}else{
ans=ExGcd(b,a%b);
ll x1=x,y1=y;
x=y1;y=x1-a/b*y1;
}
return ans;
}
bool SolveEqu(ll a,ll b,ll c){
ll d=ExGcd(a,b);
if(c%d!=0) return 0;
x*=c/d;y*=c/d;
//Minimize x
ll t=b/d;
x=(x%t+t)%t;
y=(c-a*x)/b;
return 1;
}
}
//以下为求逆元
ll Inv(ll a,ll m){
ExGcd::SolveEqu(a,m,1);
return ExGcd::x;
}

板题:洛谷P1082 同余方程,随便改改上面的程序即可。

2019/12/21

posted @   sun123zxy  阅读(545)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示