您的位置:首页 > 其它

扩展欧几里得算法

2014-05-10 17:29 232 查看
先证明下辗转相除法:

gcd(a,b)=gcd(b,a mod b)

证明:a可以表示成a = kb + r,则r = a mod b

假设d是a,b的一个公约数,则有

d|a, d|b,而r = a - kb,因此d|r

因此d是(b,a mod b)的公约数

假设d 是(b,a mod b)的公约数,则

d | b , d |r ,但是a = kb +r

因此d也是(a,b)的公约数

因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证

其中a|b是a整除b(数论中的表示)

扩展欧几里德算法是用来在已知a, b求解一组x,y使得ax+by = Gcd(a, b) =d(两边除以d,得到a'x+b'y=1,a'与b'是互质的,一定有整数解,参见初等数论的定理)。扩展欧几里德常用在求解模线性方程及方程组中。

现在求解 ax+by=1

假设a>b,a=kb+l(l<b)则上式可以写成(k * b+l)x+by = l * x+b * (k * x+y) = 1,令y' = k * x+y,则方程为l *
x + b * y' = 1

则此方程的解x为原方程的解,y = (y' - k*x)

则上述可以证明扩展欧几里得算法的正确性
给出代码:

// -- exgcd --

// ax + by == gcd(a, b), d == gcd(a, b)
1. 
void exgcd(int a, int b, int& d, int& x, int& y)
{
    if(!b) { d = a; x = 1; y = 0; }
    else { exgcd(b, a % b, d, y, x); y -= x * (a / b); }
}
2.
template<class T> void exgcd(T a, T b, T& d, T& x, T& y)
{
    if(!b) { d = a; x = 1; y = 0; }
    else { exgcd(b, a % b, d, y, x); y -= x * (a / b); }
}
// ----------


这样就可以求出一组解x,y
假设另外一组解为x1,y1
那么a(x-x1)=b(y-y1)
两边除以gcd(a,b)
则,a'(x-x1) = b'(y-y1),其中 a'=a/gcd(a.b),b'=b/gcd(a.b)
由于a',b'互素,x - x1 是b'的倍数,设为kb‘得(y - y1)=ka'可以求出所有的x和y

关于ax+by=c 当c不是gcd(a,b)时无解
由上面当c为为k*gcd(a,b)时,一组解为(kx,ky)(x,y)为ax+by=gcd(a,b)的一组解
当c不是gcd(a,b)的倍数时,显然无解,因为左边是最小公约数的倍数,右边不是

用扩展欧几里得算法可以求乘法逆元

模P乘法逆元

对于整数a、p,如果存在整数b,满足a*b mod p =1,则说,b是a的模p乘法逆元。

定理:a存在模p的乘法逆元的充要条件是gcd(a,p) = 1

证明:

充分性:

如果gcd(a,p) = 1,根据欧拉定理,aφ(p) ≡ 1 mod p,因此

显然aφ(p) - 1 mod p是a的模p乘法逆元。

必要性:

假设存在 a mod p的乘法逆元为b

ab ≡ 1 mod p

则ab = kp +1 ,所以1 = ab - kp

因为gcd(a,p) = d

所以d | 1

所以d只能为1

可以由1 = ab - kp求出b和k

计算a模p的乘法逆元

下面代码算出a,和b的最大公约数和a 模b的逆元ar,以及b模a的逆元br(用非递归的计算)

int gcd(int a,int b,int &ar,int &br){
    int x1,x2,x3;
    int y1,y2,y3;
    int t1,t2,t3;
    if(0 == a){//有一个数为0,就不存在乘法逆元
        ar = 0;br = 0 ;
        return b;
    }
    if(0 == b){
        ar = 0;
        br = 0 ;
        return a;
    }
    x1 = 1; x2 = 0; x3 = a; y1 = 0; y2 = 1; y3 = b; int k;
    for( t3 = x3 % y3 ; t3 != 0 ; t3 = x3 % y3){
        k = x3 / y3;
        t2 = x2 - k * y2;t1 = x1 - k * y1;
        x1 = y1;
        x2 = y2;
        x3 = y3;
        y1 = t1;
        y2 = t2;
        y3 = t3;
    }
    if( y3 == 1){//有乘法逆元
        ar = y2; br = x1;
        return 1;
    }
    else{//公约数不为1,无乘法逆元
        ar = 0;br = 0;return y3;
    }
}
递归的代码 求a模n的乘法逆元

bigint inv(bigint a, bigint n) {
    bigint d, x, y;
    Gcd(a, n, d, x, y);
    if (d == 1) return ( x % n + n) % n;
    else return -1;
}

http://blog.csdn.net/acdreamers/article/details/10249611
这里还有关于密钥的一些东西
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: