什么是拓展欧几里得?
所谓拓展,就是在欧几里得的基础上得出的推论。
拓展欧几里得就是根据欧几里得的原理(辗转相除),可以算出二元一次方程组的整数解和乘法逆元
拓展欧几里得求方程解:
ax + by = c
我们知道这个方程组在实数范围内是有无数个解的。
但是在整数的范围内他却存在着有限个解。
首先介绍裴蜀定理
这里再证明一下:
为什么在整数解的情况下,c一定是gcd(a,b)的倍数呢?
例:
2 * x + 4 * y = c
那么c无论如何都是偶数,换句话来说,c一定是2的倍数2 = gcd(2,4)
3 * x + 9 * y = c
那么同理c一定是3的倍数,因为上述等于 : 3 * x + 3 * 3 * y = c
3 * (x + 3 * y) = c,外面乘了个3,那么c再怎么都是3的倍数,3 = gcd(3,9)
那么按此方法可以依次类推下去,所以c = gcd(a,b)在有整数解的情况下
那么我们知道了这个,怎么来求得其所有的整数解呢?
借用下大佬的图片
由特解可以推出通解的形式
其中t为任意正整数,gcd为a,b的最大公因数,x0,和y0为特解
模板代码:
int ex_gcd(int a,int b,int &x,int &y)
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
int d = ex_gcd(b,a%b,x,y);
int t = x;
x = y;
y = t - (a/b)*y;
return d;
}
返回值是gcd(a,b),x,y最后的返回值是特解
这样就可以根据特解求出通解公式
拓展欧几里得求逆元
我们知道逆元有定义等式:
a * x ≡ 1(mod p) 其中x为逆元,p为模数
那么上述等式可以化成方程:
a * x + p * y = 1
那么利用拓展欧几里得求其一组解,其实也就求得了其逆元x
但是这里得有个前提,如果返回的a,p的最大公因数不为1,那么就不存在逆元,也就是无解
模板代码
int ex_gcd(int a,int b,int &x,int &y)
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
int d = ex_gcd(b,a%b,x,y);
int t = x;
x = y;
y = t - (a/b)*y;
return d;
}
int Inv(int a,int mod) //求a在mod下的逆元,不存在逆元返回-1
{
int x, y;
int d = ex_gcd(a, mod, x, y);
return d == 1 ? (x % mod + mod) % mod : -1; //x可能是负数,转化成正数
}