欧几里德算法总结

 

欧几里德算法

 

 

 

int Eucild(int a,int b) //欧几里德算法求gcd(a,b) { if(!a) return b; return Eucild(b%a,a); }

 

 

 

 

 

扩展欧几里德算法

 

 

扩展欧几里德算法是在欧几里德算法的基础上加了一些功能,使其不仅能够求AB的最大公约数gcd(A,B),而且能求形如Ax+By=gcd(A,B)xy的整数解。

 

 

为了便于理解扩展欧几里德算法,先来分析一下欧几里德算法求最大公约数的过程,欧几里德算法的递归出口是a0,当递归到某一层a=0时,b即为最大公约数,不难想到对于此层来说a=0, b=gcdA,B),对于此时a,b的值来说,直接就能得出如下等式a*0+b*1=gcd(A,B),很显然,对于此层递归a,b的值来说,(0,1)是方程的一组解。

 

 

下面的问题是,如果知道了下一层递归的解(x1,y1),怎么得到本曾递归的解(x,y),注意上面欧几里德算法递归调用传的参数,很容易发现,下一层递归中的a1就是本层的b%ab1是本层的a,知道了下一层a1*x1+b1*y1=gcd(A,B)的解后,我们就可以算出a*x+by=gcd(A,B)的解,过程如下:

 

 

设后一层递归得到的解为x1,y1

a1*x1+b1*y1=gcd(A,B)

 

求本曾递归a*x+b*y=gcd(A,B)的解 (其中a1=b%ab1=a)

 

 

则将a1b%a替换,b1a替换则得到如下等式

 

(b%a)*x1+a*y1=gcd(A,B)

 

(b-(b/a)*a)替换b%a得到

 

(b-(b/a)*a)*x1+a*y1=gcd(A,b)

 

整理得到

 

a*(y1-b/a*x1)+b*x1=gcd(A,b)

 

此时即可得到本曾递归的解 x=(y1-b/a*x1)y=x1

 

 

扩展欧几里德算法求解线性方程系数本质上就是一个回代的过程,在下一层递归解的基础上求出本层递归的解,当回溯到a=A,b=B时即得到了Ax+By=gcd(A,B)的解。下面用C++描述一下扩展欧几里德算法。

 

 

 

 

 

int Extended_Eucild(int a,int b,int &x,int &y) /*C语言可以用指针*/ { if(!a) { x=0; y=1; /*递归出口的解一定是x=0,y=1*/ return b; } int gcd=Eucild(b%a,a,x,y),t; /*根据下一层递归的解推出本曾递归的解*/ t=x; x=y-b/a*x; y=t; return gcd; }

 

 

扩展欧几里德解一次同余方程

 

 

下面考虑下这个问题 AxC (mod B) 求整数x

 

 

上式存在整数解的充要条件为gcd(A,B)|C,即Cgcd(A,B)的倍数。

 

 

求解的过程可以用上面扩展欧几里德算法(废话......),既然我们知道了C一定是gcd(A,B)的倍数,我们不妨先求出使得Ax+By=gcd(A,B)的整数解xy,然后等式左右乘C/gcd(A,B)后就得到一个解。

 

 

上面的方法可以得到一个整数解x,知道一个解后如何得到所有解呢?,很容易看出来,在得到一个解x后,可以在x的基础上任意加减B,得到新的解仍然满足性质。直接加减B有没有可能造成解的遗漏呢?,所以现在问题是,有没有比B更小的数,将其任意加减在x上结果还满足方程?。

 

 

假设x是方程一解,即(Ax)%B=C

 

 

让我们看一下任意在x上加减B的情况

 

A*(x+B)%B=(Ax)%B+(AB)%B=C 很显然满足方程

 

 

假设在x上加上一个小于等于B的整数B/L(L>=1)后,还满足A*(x+B/L)%B=C,则有

 

 

(Ax)%B+(AB/L)%B=C

 

 

此时必须保证AL的倍数,B也是L的倍数,并且L尽可能大,这正是gcd(A,B)的定义,故L=gcd(A,B)

 

 

所以我们求出了一个更小的数B/gcd(A,B),得到一组解x后,通过在x上任意加减B/gcd(A,B),从而得到所有满足方程的解,避免了解的遗漏。

 

 

 

下面用C++描述扩展欧几里德解一次同余方程AxC (mod B) 的过程

 

 

int x,y,gcd; gcd=Extended_Eucild(A,B,x,y); if(C%gcd==0) { /*存在解*/ x*=C/gcd; /*求出一个解*/ /*在x基础上任意加减B/gcd即得到所有解*/ } else { /*无解*/ }

 

纯原创

你可能感兴趣的:(c,算法,扩展,语言)