【算法】数论基础——逆元的概念与应用 python

文章目录

  • 前言
  • 一、什么是逆元?
  • 二、逆元的存在条件
  • 三、 如何计算逆元?
    • 1. 扩展欧几里得算法(Extended Euclidean Algorithm)
    • 2. 使用费马小定理(Fermat's Little Theorem)
  • 四、应用场景
    • 示例:求排列数和组合数


前言


逆元(Modular Multiplicative Inverse)在模运算中是一个非常重要的概念,特别是在需要执行除法操作时。因为在模 p 的情况下,直接进行除法是不可行的,我们通常会使用乘以其逆元的方式来代替除法。


一、什么是逆元?


对于给定的整数 a 和模数 m,如果存在一个整数 b 满足:(a×b)%m=1
那么 b就被称为 a 在模 m 下的乘法逆元,记作 a^-1 或者 inv(a)。

二、逆元的存在条件


逆元存在的充分必要条件是 a 和 m 互质,即 gcd(a,m)=1。当 m 是质数时,所有1≤a



三、 如何计算逆元?

1. 扩展欧几里得算法(Extended Euclidean Algorithm)


代码如下(示例):
def extend_gcd(a, b):
    if b == 0:
        return (a, 1, 0)
    
    gcd, x1, y1 = extendgcd(b, a % b)
    x = y1
    y = x1 - (a // b) * y1
    
    return (gcd, x, y)

2. 使用费马小定理(Fermat’s Little Theorem)


当 m 是质数时,根据费马小定理,对于任意 a(a 不为m 的倍数),有:

【算法】数论基础——逆元的概念与应用 python_第1张图片
可以使用快速幂算法来高效地计算这个值。

代码如下(示例):

def mod_inverse_fermat(a, m):
    return pow(a, m - 2, m)


四、应用场景


逆元广泛应用于各种算法竞赛题目、密码学以及涉及模运算的数学问题中。例如,在计算组合数时,如果要除以某个数,可以通过乘以其逆元来实现。



示例:求排列数和组合数


下面是一个完整的示例,展示了如何预计算阶乘及其逆元,并用于计算排列组合A(n,k)和C(n,k)

code:


def pre(max_n, mod): # 预计算从 0 到 max_n 的阶乘及其逆元。
    f = [1] * (max_n + 1)  # factorials
    i_f = [1] * (max_n + 1) # inverse_factorials

    for i in range(1, max_n + 1):
        f[i] = f[i - 1] * i % mod

    # 计算 max_n 的逆元
    i_f[max_n] = pow(f[max_n], mod - 2, mod)

    # 反向计算其他阶乘的逆元
    for i in range(max_n, 0, -1):
        i_f[i - 1] = i_f[i] * i % mod

    return f, i_f # 两个列表 (factorials, inverse_factorials),分别表示阶乘和阶乘的逆元。

# 计算组合数 C(n, k) = n!/( k!*(n-k)! )
def comb(n, k, f, i_f, mod): 
    if k > n or k < 0:
        return 0
    return (f[n] * i_f[k] % mod * i_f[n - k] % mod) % mod
    
 # 计算排列数 A(n, k) = n! / (n-k)!
def perm(n, k, f, i_f, mod): 
    if k > n or k < 0:
        return 0
    return (f[n] * i_f[n - k] % mod) % mod

当然,大多数时候我们只需要计算排列组合数,无需预处理出整个A/C(n,m)列表

code模板如下

mod = 10 ** 9 + 7

def C(n, m):
    p, q = 1, 1
    for i in range(1, m + 1):
        p = p * (n - i + 1) % mod
        q = q * i % mod
    return p * pow(q, mod - 2, mod) % mod

def A(n, m):
    p = 1
    for i in range(1, m + 1):
        p = p * (n - i + 1) % mod
    return p % mod


END
如果有更多问题或需要进一步的帮助,可以在评论区留言讨论哦!
如果喜欢的话,请给博主点个关注 谢谢

你可能感兴趣的:(算法,python)