欧几里得扩展

来源:互联网 发布:华彩人生软件 编辑:程序博客网 时间:2024/06/08 03:32

拓展欧几里得:

当 gcd ( a , b )= d 时,求绝对值和最小的 x , y 使得 x * a + y * b = d ;

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

设:

x1 * a + y1 * b = d ;        ①

x2 * b + y2 * ( a mod b ) = d ;   ②

因为 a mod b = a - ( a / b )* b;  ③(除法为整除)

将③代入①整理得:

y2 * a + ( x2 - ( a / b ) * y2 ) * b = d; ④

由①和④整理得:

x1 = y2 ;

y1 = x2 - ( a / b ) * y2;

将此结论代入递归函数既得。


#include<stdio.h>#define ll long longvoid gcd(ll a,ll b,ll& d,ll& x,ll& y){    if(!b){d=a;x=1;y=0;}    else {gcd(b,a%b,d,y,x);y-=x*(a/b);}}int main(){    ll a,b,d,x,y;    while(scanf("%lld%lld",&a,&b)!=EOF){        gcd(a,b,d,x,y);        printf("%lld*%lld+%lld*%lld=%lld\n",a,x,b,y,d);    }    return 0;}

拓展欧几里得求逆元:

当 a 与 b 互素时有 gcd ( a , b ) = 1 ;

即得: a * x + b * y = 1;

a * x ≡ 1 ( mod b );

由于 a 与 b 互素,同余式两边可以同除 a ,得:

1 * x ≡ 1 / a (mod b);

因此 x 是 a mod b 的逆元;

#include<stdio.h>#define ll long longll gcd(ll a,ll b,ll &d,ll& x,ll& y){    if(!b){        d=a;        x=1;        y=0;        return x;    }    else{        gcd(b,a%b,d,y,x);        y-=x*(a/b);    }    return x;}int main(){    ll a,b,d,x,y;    while(scanf("%lld%lld",&a,&b)!=EOF){        x=gcd(a,b,d,x,y);        printf("a:%lld->x:%lld\n",a,x);//        printf("a:%lld->x:%lld\nb:%lld->y:%lld\n",a,x,b,y);    }    return 0;}