扩展欧几里得和逆元

转载自https://www.cnblogs.com/zjp-shadow/p/9267675.html/
给定a,b,c都是自然数,求满足方程ax+by=c的一组解(x,y),使得x非负且最小。
由代数结构,要想有解必须满足(a,b)|c,而且(a,b)=(b,a\%b)
所以有朴素的欧几里得:

ll gcd(ll a,ll b){
    return !b?a:gcd(b,a%b);
}

时间复杂度:O(loga)
对于ax+by=c,两边同除(a,b),得:
\frac{a}{(a,b)}x+\frac{b}{(a,b)}y=\frac{c}{(a,b)}
因为\frac{a}{(a,b)}\frac{b}{(a,b)}互质,所以问题转化为新的方程ax+by=c,(a,b)=1
先求解ax+by=(a,b)=1,再把x,y同乘c即可。
又由欧几里得算法,若(x,y)满足ax+by=(a,b)(x',y')满足bx'+(a\%b)y'=bx'+(a-a/b*b)y'=(b,a\%b),由(a,b)=(b,a\%b)比较系数知:
x=y',y=x'-a/b*y',即问题exgcd(a,b,x,y)转移成了问题exgcd(b,a\%b,x',y'),然后再令x=y',y=x'-a/b*y'即可。
递归出口:b=0时,有ax=1,如果有解,只能是a=1,x=1,令y=0
扩展欧几里得:

void exgcd(ll a, ll b, ll &x, ll &y) {
    if (!b) x = 1, y = 0;
    else exgcd(b, a % b, y, x), y -= a / b * x;
}

这样求得的是一组特解,若要求x的非负最小解,只需令x=((x\%b)+b)\%b即可。
逆元:
ax≡1(modb),则称xab的逆元。这个模等式可以转化成ax=by+1,可以用扩展欧几里得求最小非负x
对于一般的ax≡c(modb)只要把逆元乘c再模b即可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。