写在前面
欧几里得算法 (gcd(a,b)) 是一个求解最大公因数的算法。比如:
gcd(42,30) = 6;
所谓 gcd,就是greatest common divisor ,最大公因数
欧几里得算法是直接求得 gcd(a,b)的值,根据中学的数学知识,我们可以得到 gcd(a,b)=gcd(b,a mod b);
这里的 mod 代表的是 取余操作。 实际上 欧几里得算法与我们学过的辗转相除法的原理是类似的,这里不做过多叙述。代码也比较简单,直接使用递归方法就可以实现。
/**
*
* @param a 第一个参数
* @param b 第二个参数
* @return 返回值 最大公因数
*/
public static long gcd(long a, long b){
if(b==0){
return a;
}
return gcd(b, a%b);
}
而 拓展欧几里得算法 则是除了得到最大公因数之外还要得到满足 ax + by = gcd(a,b) 的 x,y值
这里我们可以假设在每个步骤i中都周到 xi 和 yi都满足ri=axi+byi;
也就是可以得到如下式子:
经过推到可以得到:
(两个图片截取于书籍《密码编码学与网络安全》)
了解数学原理之后,这里直接插入代码:
/**
*
* @param a 第一个参数
* @param b 第二个参数
* @param x x的值,前两个组成的数组
* @param y y的值,前两个组成的数组
* @return 返回值为 {最大公约数,x的值,y的值}
*/
public static long[] ex_gcd(long a, long b, long[] x, long[] y){
long gcd;
long[] result = new long[3];
if(b==0){
result[0] = a;
result[1] = x[0];
result[2] = y[0];
return result;
}
long q=a/b;
long tx1 = x[0]-q*x[1];
long ty1 = y[0]-q*y[1];
long[] tx = {x[1],tx1};
long[] ty = {y[1],ty1};
return ex_gcd(b,a%b,tx,ty);
}
public static long[] ex_gcd(long a, long b){
long[] x = {1,0};
long[] y = {0,1};
return ex_gcd(a,b,x,y);
}
这样可以调用main方法实现求解:
乘法逆元:是指数学领域群G任意一个元素a,都在G中有唯一的逆元a’,具有性质 a x a’ = a’ x a = e;e代表该群的单位元。
例如:4关于1模9的惩罚逆元:
4X ≡ 1 mod 9.那么这个方程等价于求一个X和K,满足:
4X mod 9 = 1 mod 9 = 1
也就是:4X = 9K + 1
其中 X 和 K 都是整数
若 aX ≡ 1 mod f,则称 a 关于 1模f 乘法逆元为x,也可表示为 ax ≡ 1 (mod f)
如果a与f互素,那么a关于模f 的乘法逆元有解。如果不互素,则无解。如果f为素数,则从1 到 (f-1)的任意数都与f互素,即在1到 (f-1)之间都恰好有一个关于模f 的乘法逆元
例如: 求 7 关于 模 15的乘法逆元:
15 = 7x2 + 1
所以 15和 7是互素的
1 = 7 x 13 - 15 x 6
所以 7关于 模 15的乘法逆元是 13