扩展欧几里德算法计算乘法逆元详解

扩展欧几里德算法计算乘法逆元详解乘法逆元的定义 nbsp nbsp nbsp nbsp nbsp A XMODN 1 则称 X 为 A 关于模 N 的乘法逆元 注 nbsp nbsp nbsp nbsp nbsp 只有两个数互素的时候才会有乘法逆元 nbsp nbsp nbsp nbsp nbsp 两个数不互素是没有乘法逆元的 nbsp 费马小定理 利用费马小定理只能求出 N 为素数的情况下的乘法逆元 所以还是需要采用扩展欧几里德算法来计算普遍情况下的乘法逆元的情况 下面的算法是求出 n 的简化剩余集的元素个数 利用 an

乘法逆元的定义:

      A * X MOD N == 1则称X为A关于模N的乘法逆元。

注:

      只有两个数互素的时候才会有乘法逆元。

      两个数不互素是没有乘法逆元的。

 

费马小定理:

利用费马小定理只能求出N为素数的情况下的乘法逆元,所以还是需要采用扩展欧几里德算法来计算普遍情况下的乘法逆元的情况。

下面的算法是求出n的简化剩余集的元素个数,利用

an-1==1 MOD n

//n是素数,且a不能被n整除,且a与n互素才可以

              int fai = 1;

              for (int i = 2; i < n; i++)

              {

                     if (gcd(i, n) == 1)

                            fai++;

              }

              cout<<(int)pow(a, fai - 1) %n;

扩展欧几里德算法:

       N*X + A*Y == 1。

       采用逆推的方式,首先利用欧几里德算法,求最大共因子到1,

       N           A

       26          17

       17          9

       9            8

       8            1

当A为1的时候,就到了需要逆推的时候,

定义x为递归的时候a的系数,y为b的系数

1 = 9 – 8  系数为x=1和 y=-9/8==-1

 = 9 – (17 – 9 * 17/9) 除法为向下取整,系数为 x=-1=上一个的y

                                   y=1-17/9*(-1)=2其中1为上一个的x,-1为上一层y

 = ……直到结束

最后的y即为乘法逆元。

 

考虑特殊情况:

1.   当a>n的时候,例如5 * X MOD 3 == 1

此时需要将N加上A,计算5 * X MOD 8== 1

计算出乘法逆元后,y加上x即可。

5  3 =>3    2=>2     1

8     5=>5     3=>3     2=>2     1

最后计算的结果为8与5的系数,而结果需要的是5与3的系数,但是8=5+3,所以分解之后的结果为y+=x。

2.   当系数结果为负数的时候

如17 * X MOD 26 == 1,

最后Y == -3。显然乘法逆元不能为负数,且范围应为(1, N-1]之间的整数,所以需要将YMOD N即可,后在计算机内计算模余方法的缺陷,如果最后仍为负数,需要讲Y加上N。

-3+26 = 23。

利用等式加减17*26仍不变的性质。

3.   两个数不互素

输出没有乘法逆元即可。

 

运行结果:

扩展欧几里德算法计算乘法逆元详解


代码 :

#include "iostream" using namespace std; //记gcd(a,b)表示非负整数a,b的最大公因数,那么:gcd(a,b)=gcd(b,a%b) int gcd(int a, int b) { if (a < b) { int temp = b; b = a; a = temp; } if (a%b == 0) return b; else return gcd(b, a%b); } int ExtendEculid(int a, int b, int &x, int &y, int c) { if (b == 1) { x = 1; y = -c/a; return a; } int result = ExtendEculid(b, a%b, x, y, a); if (c != 0) { int temp = x; x = y; y = temp - c / a*y; } return result; } //a*x+b*y=k,调用扩展欧几里德函数 int Generate(int a, int b) { int x, y; if (b > a) { a += b; int result = ExtendEculid(a, b, x, y, 0); y += x; a -= b; } else { int result = ExtendEculid(a, b, x, y, 0); } y %= a; if (y < 0) return y + a; else return y; } int main() { while (1) { cout << "a * x mod n == 1\n请输入a:"; int a, b; cin >> a; cout << "请输入n:"; cin >> b; if (gcd(a, b) != 1) cout << "两个数不互素,没有乘法逆元!" << endl << endl; else cout << "乘法逆元是" << Generate(b, a) << endl << endl; } }




版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/210606.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 上午7:17
下一篇 2026年3月19日 上午7:17


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号