拓展欧几里得算法
可用来求最大公约数和逆元
已知gcd的写法为
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b); //辗转相除法
}
进行拓展,引入x, y,求解a * x + b * y = gcd(a, b)
int exgcd(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int g = exgcd(b, a % b, x, y);
int temp = x;
x = y;
y = temp - a / b * y;
return g;
逆元 与 a * x + b * y = gcd
的关系
a的逆元即为同余式a * x = 1(mod m)
中的x,当且仅当gcd(a,m) = 1
时x有解。
此时,相当于求a * x + m * y = 1
的解,于是,使用拓展欧几里得算法,可以得到x和y。
由于得到的x不一定是最小的,也不一定是正数,所以要进行一定的处理:(x % m + m) % m
。
其中,x % m
可以使其最小,再+ m
是为了确保为正数。
因此,在exgcd
的条件下,可以再加一个求逆函数即可。
int exgcd(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int g = exgcd(b, a % b, x, y);
int temp = x;
x = y;
y = temp - a / b * y;
return g;
int inverse(int a, int m) {
int x, int y;
int g = exgcd(a, m, x, y);
return (x % m + m) % m;