扩展欧几里得算法

本算法基于欧几里得算法故称为扩展欧几里得算法。

该算法最常见的使用情况为:求解线性同余方程 a × x ≡ c ( m o d   b ) a\times x \equiv c(mod\ b) a×xc(mod b)

  在解这个方程前,我们先来思考一个问题:如何快速解方程 a × x + b × y = g c d ( a , b ) a \times x + b\times y = gcd(a , b) a×x+b×y=gcd(a,b)

  我们引入一个定理:裴蜀定理。它说明对于任意整数 a , b a,b a,b,存在一对整数 x , y x , y x,y,满足 a x + b y = c ax+by = c ax+by=c

  这也就说明求解该方程式是可行的。

  同时,我们可以很容易想到。当b = 0时,一定有一组特解: x = 1 , y = 0 x = 1,y = 0 x=1,y=0,而当我们计算 g c d ( a , b ) gcd(a , b) gcd(a,b)时,如果用欧几里得算法,一定会产生 b = 0 b = 0 b=0的情况。所以我们可以用欧几里得算法从 b = 0 b = 0 b=0的情况递归得到所求的一组特解。同时,对于任意一个特解,可以得到通解式: x = x 0 + m × k , 其 中 m 为 模 数 x = x_0 +m\times k,其中m为模数 x=x0+m×km(利用同余的定义可以证明该式的正确性)。这就是扩展欧几里得算法的思路。

  言归正传,我们可以将 a × x ≡ c ( m o d   b ) a\times x\equiv c(mod\ b) a×xc(mod b)转换为 a × x = b + c × k ( k ∈ Z ) a\times x = b +c\times k(k\in Z) a×x=b+c×k(kZ)移项得 a × x + ( − b ) × k = c a\times x + (-b) \times k = c a×x+(b)×k=c。因为实际上我们只需要求 x x x的值即可,所以可以把 − b -b b看成 b b b那么原式就变成了 a × x + b × y = c a \times x + b\times y = c a×x+b×y=c
  然后,我们考虑当 a × x + b × y = c a \times x + b\times y = c a×x+b×y=c的时候该怎么办呢?很明显,当 c c c g c d ( a , b ) gcd(a , b) gcd(a,b)的倍数时,该式与上述式子没有本质区别,而当 c c c不为 g c d ( a , b ) gcd(a, b) gcd(a,b)的倍数时, x x x是无解的。
  当然,对于 a × x + b × y = c a \times x + b\times y = c a×x+b×y=c的情况直接用扩展欧几里得算法是没法求出特解的,因为扩展欧几里得算法实质上解的是 a × x + b × y = g c d ( a , b ) a \times x + b\times y = gcd(a , b) a×x+b×y=gcd(a,b)的解。
  因此,我们将 c c c先换为 g c d ( a , b ) gcd(a , b) gcd(a,b),求出一组解,而 a × x + b × y = g c d ( a , b ) a \times x + b\times y = gcd(a , b) a×x+b×y=gcd(a,b)相当于是将 a × x + b × y = c a \times x + b\times y = c a×x+b×y=c的等号两边同时除以 c ÷ g c d ( a , b ) c\div gcd(a ,b) c÷gcd(a,b)
  所以此时将 x x x的值乘上一个 c ÷ g c d ( a , b ) c\div gcd(a ,b) c÷gcd(a,b)即可求出 a × x + b × y = c a \times x + b\times y = c a×x+b×y=c的一组特解。而它的通解就是 x = x 0 × c g c d ( a , b ) + c g c d ( a , b ) × k x = x_0\times \frac{c}{gcd(a , b)} + \frac{c}{gcd(a,b)}\times k x=x0×gcd(a,b)c+gcd(a,b)c×k
  其中 k ∈ Z k\in Z kZ

具体代码如下:

int exgcd(int n , int m , int &x , int &y)
{
	if(m == 0)
	{
		x = 1;
		y = 0;
		return n;
	}
	int gcd = exgcd(m , n % m , y , x);
	y -= y * n / m;
	return gcd;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值