二元一次不定方程(Exgcd)(更方便的解法)
扩展欧几里得算法(Exgcd)
裴蜀定理
对于任意一组整数
Proof:
考虑数学归纳法。
当
假设存在一组整数
那么接下来证明也存在一组整数
当
那么利用辗转相除法进行递归,总能递归到
Exgcd
求关于
设
Proof:
设
。 先证必要性: 当方程有解时,方程化为
,可得 。 再证充分性: 方程
必定有解,由于 ,那么两边同乘 也必定有解。
先将方程化简,两边同除以
注意,为了方便表述,下面提到的方程都是化简后的方程。
那么我们可以先利用裴蜀定理求出
考虑如何求出通解。
让
由于
由于
通解即为:
代回原方程,可以消掉
接下来考虑,当存在正整数解时,如何求出最小正整数解与正整数解的个数。
对
先减一是为了避免
易得,当
同理,求出
由通解公式可得,
正整数解的个数即为
Ex.1 【模板】二元一次不定方程 (exgcd)
根据上面的分析,套用公式即可。
ll T,A,B,C,x,y,d,x1,x2,y1,y2,cnt;
ll GetX(ll Y){return (C-B*Y)/A;}
ll GetY(ll X){return (C-A*X)/B;}
ll Exgcd(ll a,ll b,ll &x,ll &y){
if(b==0) return x=1,y=0,a;
ll res=Exgcd(b,a%b,x,y);
ll z=x;
x=y;
y=z-(a/b)*y;
return res;
}
void Solve(){
read(A),read(B),read(C);
d=Exgcd(A,B,x,y);
if(C%d) return puts("-1"),void();
A/=d,B/=d,C/=d;
x*=C,y*=C;
x1=((x-1)%B+B)%B+1;
y2=GetY(x1);
y1=((y-1)%A+A)%A+1;
x2=GetX(y1);
cnt=(x2-x1)/B+1;
if(y2<=0) printf("%lld %lld\n",x1,y1);
else printf("%lld %lld %lld %lld %lld\n",cnt,x1,y1,x2,y2);
}
Ex.2 [NOIP2012 提高组] 同余方程
对式子进行变形:
利用 Exgcd 求解即可。
这是非常常用的变形技巧,也是当
Ex.3 青蛙的约会
设跳跃
其中
把
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】