求模乘法逆元

一、(解存在判定原理) 有限域Z(b)(b>0),对于任意整数a,若gcd(a,b)=1,则a在有限域中存在唯一的逆元x(a^-1)即a*x=1(mod b),求x

二、对于任意不同时为零的正整数a,b 求满足方程a*x+b*y=gcd(a,b)的解(x,y)。

这两种描述其实是等价的。

对于方程a*x+b*y=gcd(a,b),我们可以这样方程两边同除以gcd(a,b)得

a1*x+b1*y=1;其中a1=a/gcd(a,b) , b= b/gcd(a,b).

则gcd(a1,b1)=1;

a1*x=1-b1*y----->a1=1(mod b1)

反之亦然。

 

a*x+b*y=1( gcd(a,b)=1) 的通解为

x=x0+b*i

y=y0-a*i

证明:

设(x1,y1),(x2,y2)为方程的两组解

则a*x1+b*y1=a*x2+b*y2

->a*(x1-x2)=b*(y2-y1)

->b|[a*(x1-x2)] , gcd(a,b)=1

->b|(x1-x2)

->x2=x1+b*i;

x2代入原方程,要使方程恒立则

y2=y1-a*i;

一般化的方程a*x+b*y=c   (gcd(a,b)|c)通解为

x=x0+b/gcd(a,b)*i

y=y0-a/gcd(a,b)*i

x0,y0为a1*x+b1*y=c1的特解扩大c/gcd(a,b)倍

a1,b1,c1是a,b,c除以gcd(a,b)的结果。


exgcd()求解过程:

因为

d=gcd(a,b)=gcd(b,a%b),d=a*x+b*y

d=b*x1+(a-int(a/b)*b)*y1=a*y1+(x1-a/b*y1)

所以

x=y1

y1=x1-a/b*y1

求解模乘法逆元的代码:

typedef long long LL ; LL exgcd(LL a,LL b,LL &x,LL &y){ if( b == 0 ) { x = 1; y = 0; return a; } else{ LL x1,y1; LL d = exgcd ( b , a % b , x1 , y1 ); x = y1; y= x1 - a / b * y1; return d; } }

 

实例:poj1061

#include<iostream> using namespace std; typedef __int64 LL ; LL exgcd(LL a,LL b,LL &x,LL &y){ if( b == 0 ) { x = 1; y = 0; return a; } else{ LL x1,y1; LL d = exgcd ( b , a % b , x1 , y1 ); x = y1; y= x1 - a / b * y1; return d; } } int main() { LL x , y , m , n , l ; scanf("%I64d%I64d%I64d%I64d%I64d" , & x , & y , & m , & n , & l ); LL mn , r ; mn = m - n ; r = y - x ; if ( mn < 0 ) mn = - mn , r = -r ; LL rmn , rl ;//reverse 逆元 LL d = exgcd ( mn , l , rmn , rl ) ;// d = gcd( mn , l ) if ( r % d != 0 ) cout<<"Impossible"; else{ rmn *= ( r / d ) ; __int64 T = l / d ; printf( "%I64d" , ( rmn % T + T ) % T ) ; } return 0; }

 

你可能感兴趣的:(c)