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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Ronaldo7_ZYB/article/details/89258049

扩展欧几里得算法Exgcd

Exgcd算法内容

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


Exgcd求解一组整数解

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

由于欧几里得算法 g c d ( a , b )   =   g c d ( 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

用除法代替取模,则: a x   + b y   = b x + 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')

其中, x x' 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) 的解,用来借助这个已经求得的 x x' y y' 结合已知的 a a b b 推得现在的解 x , y . x,y. 其中 a a b b 不变。我们可以通过递归来求。

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

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
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

因此在代码实现上,我们递归到了边界是换一个处理,令 x   =   c / g c d ( 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 来说,如果有一组解 ( x 0 , y 0 ) (x_0,y_0) ,我们可以用含有 x 0 x_0 y 0 a y_0a 来解释这一个方程的通解。
我们可以通过相乘再相加抵消,来证明这一串代数式属于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)})

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


线性同余方程

线性同余方程的一组解

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

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

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

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

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

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

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


小结

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

猜你喜欢

转载自blog.csdn.net/Ronaldo7_ZYB/article/details/89258049