扩展欧几里得算法

来源:互联网 发布:mac ssh修改端口 编辑:程序博客网 时间:2024/05/16 12:16

先证明下辗转相除法:

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

这里还有关于密钥的一些东西


0 0
原创粉丝点击