扩展欧几里得模板&逆元求法

 

拓展欧几里得:

当 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 long

void 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 long

ll 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);
    }
    return 0;
}

 

MOD为素数时可以用下面2种方法求逆元

void get_inv(){
    inv[1]=1;
    for(int i=2;i<mod+5;i++)
        inv[i]=inv[mod%i]*(mod-mod/i)%mod;
}
乘法逆元

 

费马小定理:当MOD是素数时,a^(MOD-1)≡1(mod MOD)。(费马小定理是欧拉定理的特殊情况)

那么逆元x=a^(MOD-2)%MOD。可以用快速幂直接求出。

Pow(a,MOD-2,MOD)%MOD
View Code

 http://www.cnblogs.com/pk28/p/5718855.html

posted on 2016-07-29 16:23  Beserious  阅读(893)  评论(0编辑  收藏  举报