拓展欧几里得:
当 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 ",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 ",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
http://www.cnblogs.com/pk28/p/5718855.html