【数论·同余】扩展欧几里得Exgcd算法与线性同余方程求解

文章目录

    • 扩展欧几里得算法Exgcd
      • Exgcd算法内容
      • Exgcd求解一组整数解
      • Exgcd算法拓展
      • Exgcd算法通解
    • 线性同余方程
      • 线性同余方程的一组解
      • 线性同余方程的通解
      • 线性同余方程的最小正整数解
    • 小结

扩展欧几里得算法Exgcd

Exgcd算法内容

给定 a , b , c , d a,b,c,d a,b,c,d,求解 a x   + b y   =   g c d ( a , b ) ax\ +by\ =\ gcd(a,b) ax +by = gcd(a,b)中的任意正数解 ( x , y ) (x,y) (x,y)


Exgcd求解一组整数解

我们可以根据裴蜀定理,证明方程一定有解。

由于欧几里得算法 g c d ( a , b )   =   g c d ( b , a   %   b ) gcd(a,b)\ =\ gcd(b,a\ \%\ b) gcd(a,b) = gcd(b,a % b),则有:
a x   + b y   = b x   +   ( a   %   b ) ∗ y ax\ +by\ =bx\ +\ (a\ \%\ b)*y ax +by =bx + (a % b)y

用除法代替取模,则: a x   + b y   = b x ′ + y ′ ( a − [ a / b ] ∗ b ) ax\ +by\ =bx'+y'(a-[a/b]*b) ax +by =bx+y(a[a/b]b)

通过乘法分配律和结合律的运算可得: a x + b y = a y ′ + b ( x ′ − [ a / b ] ∗ y ′ ) ax+by=ay'+b(x'-[a/b]*y') ax+by=ay+b(x[a/b]y)

其中, x ′ x' x y ′ y' y是方程 b x + y ( a − [ a / b ] ∗ b ) = g c d ( b , a % b ) bx+y(a-[a/b]*b)=gcd(b,a\%b) bx+y(a[a/b]b)=gcd(b,a%b)的解,用来借助这个已经求得的 x ′ x' x y ′ y' y结合已知的 a a a b b b推得现在的解 x , y . x,y. x,y.其中 a a a b b b不变。我们可以通过递归来求。

递归的边界:
a x + b y = g c d ( a , 0 ) ax+by=gcd(a,0) ax+by=gcd(a,0)时,即 b = 0 b=0 b=0时, x = 1   y = 0. x=1\ y=0. x=1 y=0.

#include
#include
#include
#include
using namespace std;
int x,y;
int exgcd(int a,int b)
{
	if (b==0) 
	{ 
	    x=1; 
		y=0; 
		return a; 
	}
	int n=exgcd(b,a%b);
	int t=x;
	x=y; 
	y=t-a/b*y;
	return n;
}
int main(void)
{
	int a,b;
	cin>>a>>b;
	cout<<exgcd(a,b)<<endl;//这里输出最大公约数
	cout<<x<<' '<<y<<endl;//这个输出方程ax+by=gcd(a,b)的解
	return 0;
}

Exgcd算法拓展

根据裴蜀定理,我们可以得到如下方程的解:

a x   +   b y   =   c ,   g c d ( a , b )   ∣   c ax\ +\ by\ =\ c,\ gcd(a,b)\ |\ c ax + by = c, gcd(a,b)  c

因此在代码实现上,我们递归到了边界是换一个处理,令 x   =   c / g c d ( a , b ) ,   y   =   0 x\ =\ c/gcd(a,b),\ y\ =\ 0 x = c/gcd(a,b), y = 0

代码实现和上述代码基本相似。


Exgcd算法通解

对于方程 a x   +   b y   =   c ,   g c d ( a , b )   ∣   c ax\ +\ by\ =\ c,\ gcd(a,b)\ |\ c ax + by = c, gcd(a,b)  c来说,如果有一组解 ( x 0 , y 0 ) (x_0,y_0) (x0,y0),我们可以用含有 x 0 x_0 x0 y 0 a y_0a y0a来解释这一个方程的通解。
我们可以通过相乘再相加抵消,来证明这一串代数式属于Exgcd算法的通解:
( x 0   +   k ∗ b g c d ( a , b )        ,        y 0   +   k ∗ a g c d ( a , b ) ) (x_0\ +\ k*\frac{b}{gcd(a,b)}\ \ \ \ \ \ ,\ \ \ \ \ \ y_0\ +\ k*\frac{a}{gcd(a,b)}) (x0 + kgcd(a,b)b      ,      y0 + kgcd(a,b)a)

显然,两个数字乘上 a , b a,b a,b以后再相加,结果一定等于 x 0 + y 0 x_0+y_0 x0+y0 k k k取任意整数。


线性同余方程

线性同余方程的一组解

现在我们需要求解有关 x x x的线性同余方程: a   ∗   x   ≡   b   ( m o d   m ) a\ *\ x\ \equiv\ b\ (mod\ m) a  x  b (mod m)
变形一下,就变成了: a ∗ x   −   b   ≡   0     ( m o d   m ) a*x\ -\ b\ \equiv\ 0\ \ \ (mod\ m) ax  b  0   (mod m)

然后我们就可以发现 a ∗ x   −   b a*x\ -\ b ax  b一定是 m m m的倍数,因此我们设是 m m m − y -y y倍,则可以将同余式变形为等式:
a ∗ x   − b   =   − y ∗ m ⟹ a ∗ x + y ∗ m   =   b a*x\ -b\ =\ -y*m\Longrightarrow a*x+y*m\ =\ b ax b = ymax+ym = b
现在我们就变形为了一个扩展欧几里得算法的形式,即可运用上述算法求出对应的解 x x x


线性同余方程的通解

我们知道扩展欧几里得的通解形式是:
( x 0   +   k ∗ b g c d ( a , b )        ,        y 0   +   k ∗ a g c d ( a , b ) ) (x_0\ +\ k*\frac{b}{gcd(a,b)}\ \ \ \ \ \ ,\ \ \ \ \ \ y_0\ +\ k*\frac{a}{gcd(a,b)}) (x0 + kgcd(a,b)b      ,      y0 + kgcd(a,b)a)

再结合线性同余方程的欧几里得式:
a ∗ x + y ∗ m   =   b a*x+y*m\ =\ b ax+ym = b

我们考虑对每一个 x x x求出通解:

  • 不难知道在这里m就是通解形式中的b,而任意一个数加上了 k ∗ m g c d ( a , m ) k*\frac{m}{gcd(a,m)} kgcd(a,m)m以后,一定有:
    k ∗ m g c d ( a , m ) ≡   x k*\frac{m}{gcd(a,m)} \equiv\ x kgcd(a,m)m x
    因此只要满足 m g c d ( a , m ) \frac{m}{gcd(a,m)} gcd(a,m)m与x同余的数就是方程的通解。

线性同余方程的最小正整数解

我们知道了方程的通解,则另 P   =   m g c d ( a , m ) P\ =\ \frac{m}{gcd(a,m)} P = gcd(a,m)m,对于任意一个整数解 x 0 x_0 x0,则有最小正整数解: x   =   ( x   %   P   +   P )   %   P x\ =\ (x\ \%\ P\ +\ P)\ \%\ P x = (x % P + P) % P


小结

Exgcd和线性同余方程是一个数论的模型,要熟记结论,灵活应用。许多的扩展和变形要需要以这两个算法为根本。

你可能感兴趣的:(数学·数学推导)