寒假集训专题四-D.同余方程
d-同余方程
解同余方程的通法
注意:gcd的两个参数一定是正值
对于
Ax≡B(mod M)---->Ax=My+B---->Ax+My=B(正负号不重要),因为解出的x或者y可以通过整体式子+-lcm 的倍数来变化
于是就是解Ax+My=B这个不定方程。
根据斐蜀定理:ax+by=c=k∗gcd(a,b)(k∈N∗)
所以必须gcd(A,M)|B,否则无解。
//这里需要特别判断
设a>b。
当b=0,gcd(a,b)=ab=0,gcd(a,b)=a,所以此时x=1,y=0x=1,y=0
当a>b>0a>b>0时,设ax1+by1=gcd(a,b),bx2+(a mod b)y2=gcd(b,a mod b)
根据欧几里德原理,则
ax1+by1=bx2+(a mod b)y2
即ax1+by1=bx2+(a−(a/b)∗b)y2=ay2+bx2−(a/b)∗by2
对应得x1=y2,y1=x2−(a/b)∗y2
于是我们就可以一边求gcd一边解这个方程。
当然,注意到跑了exgcd后解出来的是ax+by=gcd(a,b)
解同时乘上c/gcd(a,b)
注意到x,y的解不止一个,x+=b/gcd(a,b),y−=a/gcd(a,b)
后总是合法。(因为加减的都是ab/gcd(a,b)=lcm(a,b)
。
为了求最小正整数值,我们模这个值即可。
求这一步之前,要先判断x的正负与否
如果要把最后一步套路化,就是D=gcd(A,B),x=x∗(B/D)%(M/D)
代码
#include<bits/stdc++.h> using namespace std; using ll = long long; ll exgcd(ll a, ll b ,ll &x,ll &y) { if(b==0) {x=1,y=0;return a;}; ll d=exgcd(b,a%b,x,y); //这一步交换的处理很重要 ll z=x;x=y,y=z-a/b*y; return d; } ll gcd(ll x,ll y) { if(y==0) return x; return gcd(y,x%y); } signed main() { ll a,b,x,y; cin>>a>>b; ll m=gcd(a,b); //这里其实要判断 ?gcd(a,b)|1,答案是肯定的,题目已经保证了 ll d=exgcd(a,b,x,y); if(x<0) { while(x<0) { x=x+b/m; } } //这里1即同余方程右边的值,由于是1可要可不要 cout<<x*(1/m)%(b/m); }
本文作者:TimMCBen
本文链接:https://www.cnblogs.com/TimMCBen/p/15996647.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步