51 nod 1256 乘法逆元

例如:4关于1模7的乘法逆元为多少?
4X≡1 mod 7
这个方程等价于求一个X和K,满足
4X=7K+1
其中X和K都是整数。
若ax≡1 mod f, 则称a关于模f的乘法逆元为x。也可表示为ax≡1(mod f)。
当a与f互素时,a关于模f的乘法逆元有唯一解。如果不互素,则无解。如果f为素数,则从1到f-1的任意数都与f互素,即在1到f-1之间都恰好有一个关于模f的乘法逆元。
例如,求5关于模14的乘法逆元:
14=5*2+4
5=4+1
说明5与14互素,存在5关于14的乘法逆元。
1=5-4=5-(14-5*2)=5*3-14
因此,5关于模14的乘法逆元为3。
其求法可用 欧几里德算法:
Extended Euclid (d,f) //算法求d关于模f的乘法逆元d -1 ,即 d* d -1 mod f = 1
1 。(X1,X2,X3) := (1,0,f); (Y1,Y2,Y3) := (0,1,d)
2。 if (Y3=0) then return d -1 = null //无逆元
3。 if (Y3=1) then return d -1 = Y2 //Y2为逆元
4。 Q := X3 div Y3 //整除
5。 (T1,T2,T3) := (X1 - Q*Y1,X2 - Q*Y2,X3 - Q*Y3)
6 。(X1,X2,X3) := (Y1,Y2,Y3)
7。 (Y1,Y2,Y3) := (T1,T2,T3)
8。 goto 2

常用于加密算法中,如仿射算法。


#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
//返回d=gcd(a,b);和对应于等式ax+by=d中的x,y 
long long extend_gcd(long long a, long long b, long long &x, long long &y){
	if(a == 0 && b == 0)
	    return -1;//无最大公约数 
	if(b == 0){
		x = 1;
		y = 0;
		return a;
	}
	long long d = extend_gcd(b, a % b, y, x);
	y -= a / b * x;
	return d;
}
//*********求逆元素*******************  
//ax = 1(mod n)  
long long mod_reverse(long long a, long long n){
	long long x, y;
	long long d = extend_gcd(a, n, x, y);
	if(d == 1)
		return (x % n + n) % n;
	else 
	    return -1;
}
int main(){
	long long n, m;
	while(~scanf("%d%d", &m, &n)){
		printf("%lld\n", mod_reverse(m, n));
	}
	return 0;
} 


你可能感兴趣的:(C语言,51,nod,乘法逆元)