求逆元的三种方法

1什么是逆元?


如果 1/a ≡ x ( mod p ),称 x 是 a 的逆元(在 mod p 意义下,p 为一个大质数)。你可能会不理解吧,1/a 不是整数啊,x 却是整数,怎么会有同余关系呢?你可以理解成 ·b 和 /a 的效果是一样的,即除以 p 的余数是一样的。比如 b 是 a 的倍数,x 是 a 的逆元,那么一定有 b · x ≡ b / a ( mod p )。


2求法一(扩展欧几里得算法)


如果 x 是 a 的逆元,那么显然 x · a ≡ 1 ( mod p ),x · a - 1 ≡ 0 ( mod p )。假设 x · a -  1 = py,所以 ax + py = 1。由于 a 和 p 互质,即 gcd ( a,p ) = 1,这个不定方程就可以用 扩展欧几里得算法 来求解了,求得的 x 即为 a 的逆元。


3求法二(费马小定理与快速幂)


x · a ≡ 1 ( mod p ),即一个 a 的倍数 mod p = 1,这是不是让你想起了 费马小定理?a ^ ( p - 1 ) ≡ 1 ( mod p ),其中 p 是质数,当然这只是 欧拉定理 的一个特例。因此 x = a ^ ( p - 2 ) 为 a 的逆元。在用编程来求 a ^ ( p - 1 ) 时,如果直接一个一个乘,显然太慢了(p 是一个大质数)。其实,求较大幂次有一个很好实现又很快的方法:快速幂,时间复杂度是 log 级别的。


4求法三(线性批量求逆元)


p 可以写成 ak + r,其中 r 为除以 a 的余数。ak + r ≡ 0 ( mod p ),两边同时乘以 a^(-1) · r^(-1),得到 k · r^(-1) + a^(-1) ≡ 0 ( mod p )。再移项,得到 a 的逆元 a^(-1) ≡ - k · r^(-1) ( mod p )。r^(-1) 是 r 的逆元,这相当于一个递推的过程。即如果 i 的逆元记作 inv[ i ],则 inv[ i ] ≡ - ( p / i ) · inv [ p mod i ] ( mod p )。这样做的好处是可以线性求得很多个数的逆元,但同时需要一定的存储空间。


5后记


针对不同的题目,应选取不同的做法,这 3 种求逆元的方法也各有千秋。现在你知道如何快速求组合数 C ( m,n ) mod p 了吧?

### 计算数学中的逆元 #### 定义与概念 在数论中,给定两个整数 \(a\) 和 \(m\),如果存在一个整数 \(b\) 使得 \((a * b) \% m = 1\) 成立,则称 \(b\) 是 \(a\) 模 \(m\) 的乘法逆元。这意味着当 \(a\) 和 \(m\) 互质时,\(a\) 存在一个唯一的模 \(m\) 下的乘法逆元。 #### 使用 `gmpy2` 库求解逆元 Python 中可以利用第三方库 `gmpy2` 来高效地计算大整数下的乘法逆元。通过导入 `invert()` 函数可以直接调用来获取结果[^2]: ```python from gmpy2 import invert def find_inverse(x, y): try: result = invert(x, y) return f"The modular multiplicative inverse of {x} mod {y} is {result}" except ZeroDivisionError as e: return str(e) print(find_inverse(3, 7)) ``` #### 扩展欧几里得算法实现 另一种常见的方法是采用扩展欧几里得算法来寻找满足条件的最大公因数等于1的情况,从而得出对应的逆元值。此方法适用于任意正整数对之间的运算而不局限于特定范围内的数值[^4]: ```cpp // C++ implementation using Extended Euclidean Algorithm int gcdExtended(int a, int b, int &x, int &y){ if (a == 0){ x = 0; y = 1; return b; } int x1, y1; int gcd = gcdExtended(b % a, a, x1, y1); x = y1 - (b / a) * x1; y = x1; return gcd; } bool modInverse(int A, int M){ int x, y; int g = gcdExtended(A, M, x, y); // If the GCD isn't 1 then there's no solution. if(g != 1) cout << "No Solution"; else{ // Ensure positive value for modulo operation int res = (x%M + M) % M; printf("Modular Multiplicative Inverse is %d", res); } } ``` #### 幂取模快速幂算法 对于某些特殊情况,比如费马小定理适用的情形 (\(p\) 为素数),可以通过快速幂的方式简化计算过程并提高效率。具体来说就是基于公式 \(inv(a)=a^{p-2}\%p\): ```cpp #include <iostream> using namespace std; long long power(long long base,long long exp,long long MOD){ long long answer=1; while(exp>0){ if(exp&1)//if odd number answer=(answer*base)%MOD; base=(base*base)%MOD; exp>>=1;//divide by two } return answer; } void fastPowerMethod(){ const long long P=987654321LL; // example prime modulus for(int i=1;i<=10;++i){ cout<<power(i,P-2,P)<<endl; } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值