扩展欧几里得算法详解



对于不完全为 0的非负整数abgcd(a,b)表示ab的最大公约数,必然存在整数xy,使得gcd(a,b)=ax+by


解析:

ab不全为0,令a>b

b=0时,gcd(a,b)=a,解的情况为x=1y=0

ab=0,令a*x1+b*y1 = gcd(a,b),所以b*x2+(a%b)*y2 =gcd(b,a%b)

gcd(a,b) = gcd(b,a%b)(欧几里得算法)

故有a*x1+b*y1 = b*x2+(a%b)*y2

 = b*x2+( a-(a/b)*b )*y2
              = b*x2+a*y2-(a/b)*b*y2
              = a*y2+b*(x2-(a/b)*y2)
即有x1=y2, y1=x2-(a/b)*y2
因此x1y1的值可由x2y2推知,拓展欧几里得算法的求解过程就是不断地的将b放小,直至b等于0,最后反推求xy

//Date:2015.05.05
//扩展欧几里得算法的递归与非递归实现

#include 
#include 
#include 
using namespace std;

int recursive_gcd(int a,int b,int &x,int &y){
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    int r=recursive_gcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=t-a/b*y;
    return r;
}

int iterative_gcd(int m,int n,int &x,int &y){
    int x1,y1,x0,y0;
    x0=1;x1=0;x=0;
    y0=0;y1=1;y=1;

    int r=m%n;
    int q=m/n;
    while(r){
        x=x0-q*x1;x0=x1;x1=x;
        y=y0-q*y1;y0=y1;y1=y;
        m=n; n=r; r=m%n;
        q=m/n;
    }
    return n;
}

int main(){
    int a,b,x,y,r;
    mt19937 engine(time(NULL));
    uniform_int_distribution distribution(0,100000);
    a=distribution(engine);b=distribution(engine);

    printf("a*x+b*y=gcd(a,b)\n");
    r = recursive_gcd(a,b,x,y);
    printf("递归 : (%d) * (%d) + (%d) * (%d) = %d\n",a,x,b,y,r);
    r = iterative_gcd(a,b,x,y);
    printf("迭代 : (%d) * (%d) + (%d) * (%d) = %d\n",a,x,b,y,r);
    return 0;
}

应用:

1.求解不定方程ax+by=c :

对于不定整数方程ax+by=c ,若cmod gcd(a,b)=0,则该方程存在整数解,否则不存在整数解。 

故当c mod gcd(a,b)=0时,先用扩展欧几里得算法求出ax+by=gcd(a,b)的一组解x1,y1

k= c/gcd(a,b);则x2=x1*ky2=y1*kax+by=c的一组解。

x=x2+b/gcd(a,b)*ty=y2-a/gcd(a,b)*t (t为整数),即为ax+by=c的所有解。

 

2.求解乘法逆元

在密码学中,有限域GF(p)是一个很重要的域,其中p为素数。简单来说,GF(p)就是mod p,因为一个数模p后,结果在[0, p-1]之间。GF(p)里面的乘法即为一般的乘法运算。为什么p一定要是一个素数呢?这是因为当p为素数时,才能保证集合中的所有的元素都有乘法逆元(0除外)。假设p等于10,对于元素2,找不到一个数x,使得2*x mod10等于1。如果p是素数,那么对于域中的任一个元素a,总能在域中找到另外一个元素x,使得a*xmod p等于1,其中a与互为乘法逆元。也即若gcd(a,p)=1;则ax+py=1

 

但是我们希望0255256个数字也能组成一个域,因为很多领域需要用到。mod 256的余数范围是0255,不过256不是素数。为此我们定义一个素多项式m(x)=x^8+ x^4 + x^3 +x +1(类似素数,素多项式不能表示为其他两个多项式的乘积),于是0255可以通过mod m(x)这样的方式组成一个域GF(2^8),域中的每一个元素都存在乘法逆元(0的乘法逆元定义为0)

注:有限域GF(2^8)中的加法运算为异或运算,减法与加法等价。

//Date:2015.05.05
//扩展欧几里得算法求解有限域GF(2^8)内的乘法逆元

#include
using namespace std;
const int Bit_Num=sizeof(int)*8;

//求解非零最高位
int index_of_max(int value){
    int index=0;
    for(int i=0;i

你可能感兴趣的:(算法类)