参考
《算法笔记》(胡凡)
扩展欧几里得算法
求解ax+ by = gcd(a, b)
int exGcd(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int gcd = exGcd(b, a % b, x, y);
int tmp = x;
x = y;
y = tmp - (a / b) * y;
return gcd;
}
全部解: x' = x + b / gcd * K (K为任意整数)
y' = y - a / gcd * K
x的最小非负整数解:(x % (b / gcd) + (b / gcd)) % (b / gcd)
方程ax + by = c求解
ax + by = c存在解的充要条件是c % gcd = 0
其中一组解为(x0, y0) = (cx / gcd, cy / gcd),x、y即为上面代码求出的ax + by = gcd的解
全部解:x' = cx / gcd + b / gcd * K (K为任意整数)
y' = cy / gcd - a / gcd * K
同余式ax ≡ c (mod m)求解
等价于求解ax + my = c,c % gcd(a,m) = 0时才有解,先求ax + my = gcd(a,m),得到(x,y),进而按照公式得到ax + my = c中x的全部解:x' = cx / gcd + m / gcd * K (K为任意整数),当K取0、1、2...、gcd(a,m) - 1时所得到的解在模m意义下是不同的
逆元的求解
乘法逆元:ab ≡ 1 (mod m)成立,则称a和b互为模m的逆元
gcd(a,m) = 1则有解,取最小非负整数解(x % m + m) % m为逆元
另外,如果符合费马小定理,可以使用该定理
费马小定理:设m是素数,a是任意整数且a不为m的整数倍,则a ^ (m - 1) ≡ 1(mod m)。
即a ^ (m - 2) % m即为逆元,用快速幂求解
(b / a) % m的计算
转换为(b * x) % m,x为a模m的逆元,此时b可以已经取过模,不是原始值
若gcd(a, m) ≠ 1,使用(b / a) % m = (b % (am)) / a