前言
在noip前就对此算法进行过一些了解,然而noipD1T1压根没想到扩欧,说明我之前学的东西根本不扎实,于是现在跑来补坑
相关概念:
可以先看看这位dalao的博客,同时下面很多定理的证明那个博客也一并给出:
https://blog.csdn.net/yoer77/article/details/69568676
更项减损法&欧几里得算法
先来介绍一个在《九章算术》中出现的更相减损法:
对于任意正整数\(a>=b\),都有\(gcd(a,b)=gcd(b,a-b)=gcd(a,a-b)\)
证明:
对于a,b任意公约数d,因为\(d\mid b,d|a\),所以\(d\mid (a-b)\),所以a,b的公约数集合与\(b,a-b\)的公约数集合相同,对于\(a,a-b\)也同理。
然后就是大名鼎鼎的欧几里得算法:
对于任意正整数$a,b (b \ne 0) $ 有, \(gcd(a,b)=gcd(b,a\mod b)\)
进行高精度运算时,可考虑更项减损法代替。
裴蜀定理(\(Bézout's\) \(lemma\))
对于任意整数\(a,b\),存在一对整数,满足\(ax+by=gcd(a,b)\)
证明:
我觉的还是《算法竞赛进阶指南》中给出证明更有帮助:
在欧几里得算法最后一步,即\(b=0\)时,显然有一对整数\(x=1,y=0\),满足\(a*1+b*0=gcd(a,0)\)
若\(b > 0\),则\(gcd(a,b)=gcd(b,a \mod b)\)。假
设存在一对整数\(x,y\),满足\(b*x+(a \mod b)*y=gcd(b,a \mod b)\),
因为\(bx+(a \mod b)y\)
\(=bx+(a-b\lfloor a/b \rfloor)y\)
\(=ay-b(x-\lfloor a/b \rfloor y)\),
所以令\(x'=y,y'=x-\lfloor a/b \rfloor y\)就能得到\(ax'+by'=gcd(a,b)\)
应用数学归纳法(如果您不知道这是什么,您可以把它想象成一个递推或递归过程),可知此定理成立。
上述证明过程还给出了\(x,y\)的计算过程,用代码写就是
ll ex_gcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1,y=0;
return a;
}
ll d=ex_gcd(b,a%b,x,y);
ll z=x;x=y,y=z-(a/b)*y;
return d;
}
ex_gcd返回\(gcd(a,b)\),同时求出一组解\(x,y\)
对于\(ax+by=c\),它有解当且仅当\(gcd(a,b)\mid c\)
然后,此方程的通解可表示为:
\(x=(c/d)*x0+k*(b/d)\) ,\(y=(c/d)*y0-k*(a/d)\)
其中\(k\)取任意整数,\(d\)为\(gcd(a,b)\).
这是为什么呢?我辗转于各大博客都无清楚的解释,在我坚韧不拔意志的驱使下,终于在洛谷网课上找到了一个简洁易懂的证明:
证明:
我们先考虑:\(ax+by=gcd(a,b)\)的情况,
显然\(a*b+b*(-a)=0\) 同时除以\(gcd(a,b)\),易知这是可行的
所以\(a*(b/gcd(a,b))+b*(-a/gcd(a,b))=0\)
所以若已知\(x0,y0\)为一组特解即\(a*x0+b*y0=gcd(a,b)\),不妨令\(x=x0+k*b/gcd(a,b)\) ,\(y=y0-k*(a/gcd(a,b))\),
带入\(ax+by\)得\(a(x0+k*b/gcd(a,b))+b*(y0-k*(a/gcd(a,b)))\)
\(=ax0+by0+k*(a*b/gcd(a,b)-b*a/gcd(a,b))\)
\(=ax0+by0=gcd(a,b)\)
然后\(ax+by=c\)的也很好解决掉了,这里不赘述
相关
求解线性同余方程
对于方程\(a*x \equiv b \pmod m\),可以转化为\(a*x-b \equiv 0 \pmod m\),不妨设\((a*x)-b\)为\(m\)的\(-y\)倍,即\(a*x-b=-y*m\)
得到\(a*x+m*y=b\)
然后就见上文处理了
求逆元
逆元是什么?见我的这篇博客:https://www.luogu.org/blog/Rye-Catcher/solution-p3811
\(a*x \equiv 1 \pmod b\)也就转换成\(ax+by=1\)了
然后见上文处理
例题: