转载自https://www.cnblogs.com/zjp-shadow/p/9267675.html/
给定,
,
都是自然数,求满足方程
的一组解
,使得
非负且最小。
由代数结构,要想有解必须满足,而且
。
所以有朴素的欧几里得:
ll gcd(ll a,ll b){
return !b?a:gcd(b,a%b);
}
时间复杂度:
对于,两边同除
,得:
。
因为和
互质,所以问题转化为新的方程
。
先求解,再把
同乘
即可。
又由欧几里得算法,若满足
,
满足
,由
比较系数知:
,即问题
转移成了问题
,然后再令
即可。
递归出口:时,有
,如果有解,只能是
,令
。
扩展欧几里得:
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;
}
这样求得的是一组特解,若要求的非负最小解,只需令
即可。
逆元:
,则称
是
模
的逆元。这个模等式可以转化成
,可以用扩展欧几里得求最小非负
。
对于一般的只要把逆元乘
再模b即可。
