计算逆元的三种方法

计 算 逆 元 的 三 种 方 法 计算逆元的三种方法

一、首先是两种O(log)时间求单个数的逆元

我们要求 a a a在模 p p p意义下的逆元
其中 a a a是小于 p p p的正整数, p p p是一个素数

① 费马小定理:

由费马小定理 a p − 1 ≡ 1   ( m o d   p ) a^{p-1}≡1\ (mod\ p) ap11 (mod p)可以得到:
a ⋅ a p − 2 ≡ 1   ( m o d   p ) a\cdot a^{p-2}≡1\ (mod\ p) aap21 (mod p)
所以可以直接使用快速幂求出 a p − 2 a^{p-2} ap2即为 a a a在模 p p p意义下的逆元

② 扩展欧几里得:

先假设我们要求的 a a a在模 p p p意义下的逆元为 x x x
可以得到方程 a ⋅ x ≡ 1   ( m o d   p ) a\cdot x≡1\ (mod\ p) ax1 (mod p)
变成一般等式: a ⋅ x + p ⋅ y = 1 a\cdot x+p\cdot y=1 ax+py=1
现在要求的就是 x x x
p p p是素数,所以 g c d ( a , p ) = 1 gcd(a,p)=1 gcd(a,p)=1,可以使用扩展欧几里得计算得到 x x x

二、线性求逆元:

显然 1 − 1 = 1 1^{-1}=1 11=1
假设现在已经计算出 i i i之前的所有正整数的逆元
现在要求 i i i的逆元
先写出等式: i ⋅ k + r = p i\cdot k+r=p ik+r=p
变成模 p p p下的恒等式: i ⋅ k + r ≡ 0   ( m o d   p ) i\cdot k+r≡0\ (mod\ p) ik+r0 (mod p)
两边同乘 i − 1 ⋅ r − 1 i^{-1}\cdot r^{-1} i1r1得到: k ⋅ j − 1 + i − 1 ≡ 0   ( m o d   p ) k\cdot j^{-1}+i^{-1}≡0\ (mod\ p) kj1+i10 (mod p)
移相: i − 1 ≡ − k ⋅ j − 1   ( m o d   p ) i^{-1}≡-k\cdot j^{-1}\ (mod\ p) i1kj1 (mod p)
k k k j j j可以分别用 p / i p/i p/i p % i p\%i p%i来代替: i − 1 ≡ − ( p / i ) ⋅ ( p % i ) − 1   ( m o d   p ) i^{-1}≡-(p/i)\cdot (p\%i)^{-1}\ (mod\ p) i1(p/i)(p%i)1 (mod p)
取 正 数 : i − 1 = ( p − p / i ) ⋅ ( p % i ) − 1 % p 取正数:i^{-1}=(p-p/i)\cdot (p\%i)^{-1}\%p i1=(pp/i)(p%i)1%p
p % i < i p\%i<i p%i<i 所以 p % i p\%i p%i的逆元已经算出来了,右端项没有未知数。所以就可以 O ( n ) O(n) O(n)的时间内算出 1 − n 1-n 1n之内所有数的逆元了

inv[1] = 1;
for(int i = 1; i <= n; i++)
	inv[i] = (p-p/i)*inv[p%i]%p;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
26在模意义下的乘法逆元是指另一个整数x,使得26与模数取模后相乘等于1,即 $26x \equiv 1 \pmod{m}$,其中m为模数。 有多种方法可以计算乘法逆元,下面介绍两种常见的方法。 ### 扩展欧几里得算法 扩展欧几里得算法可以求解形如 $ax + by = \gcd(a,b)$ 的线性方程,其中a和b为任意整数。当a和模数m互质时,即 $\gcd(a,m) = 1$ 时,可以通过扩展欧几里得算法求出a在模m意义下的乘法逆元。 具体做法是,首先用欧几里得算法求出$\gcd(a,m)$,同时记录下每一步中的商和余数,然后从最后一步开始逆推,得到 $ax + my = \gcd(a,m)$ 的一组解,其中x即为a在模m意义下的乘法逆元。 以下是Python代码实现: ```python def ext_euclid(a, b): if b == 0: return a, 1, 0 else: d, x, y = ext_euclid(b, a % b) return d, y, x - (a // b) * y def mod_inv(a, m): d, x, y = ext_euclid(a, m) return x % m if d == 1 else None # 计算26在模37意义下的乘法逆元 inv = mod_inv(26, 37) print(inv) # 输出16 ``` ### 快速幂算法 当模数m为素数时,可以用费马小定理来计算乘法逆元。具体来说,如果a和m互质,那么 $a^{m-1} \equiv 1 \pmod{m}$,因此 $a \cdot a^{m-2} \equiv 1 \pmod{m}$,即$a^{m-2}$是a在模m意义下的乘法逆元。 对于一般的模数,可以先将模数分解为若干个不同的素数的乘积,然后对每个素数分别用费马小定理计算乘法逆元,最后利用中国剩余定理合并结果。但是这种方法比较繁琐,不如直接使用扩展欧几里得算法。 以下是Python代码实现: ```python def mod_pow(a, b, m): # 快速幂算法,计算a^b mod m res = 1 while b > 0: if b % 2 == 1: res = (res * a) % m a = (a * a) % m b //= 2 return res def mod_inv(a, m): # 计算a在模m意义下的乘法逆元 return mod_pow(a, m - 2, m) # 计算26在模37意义下的乘法逆元 inv = mod_inv(26, 37) print(inv) # 输出16 ``` 以上两种方法都可以求解26在模37意义下的乘法逆元,结果均为16。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值