📜  当一个数 A 提升到 N 阶乘除以 P 时求余数(1)

📅  最后修改于: 2023-12-03 15:25:36.005000             🧑  作者: Mango

求解 A! mod P

在很多数学问题和计算机算法中,需要计算 A! (A 的阶乘) 除以某个数 P 的余数。本文将介绍一些解决这个问题的方法。

直接计算

最直接的方法就是计算 A 的阶乘然后再除以 P 取余数。下面是一个用 Python 实现的例子:

def factorial_modulo(a, p):
    fact = 1
    for i in range(1, a+1):
        fact = (fact * i) % p
    return fact

# 测试
print(factorial_modulo(5, 7))  # 1
print(factorial_modulo(10, 13))  # 11

这种方法的缺点是对于比较大的数 A 计算量很大,可能会溢出。因此,我们需要更有效的算法。

Wilson 定理

Wilson 定理是一种用于计算 A! mod P 的方法,其中 P 是一个质数。定理的表述为:如果 P 是一个质数,则 (P-1)! ≡ -1 (mod P)。因此,如果 A < P,可以直接使用 Wilson 定理计算 A! mod P。

下面是一个用 Python 实现 Wilson 定理的例子:

def factorial_modulo_wilson(a, p):
    if a >= p:
        return 0
    if a == 0:
        return 1
    fact = p - 1
    for i in range(a+1, p):
        fact = (fact * i) % p
    return ((-1)**(p-1-a)) * fact % p

# 测试
print(factorial_modulo_wilson(5, 7))  # 1
print(factorial_modulo_wilson(10, 13))  # 11
威尔逊定理的扩展

如果 P 不是一个质数,我们可以使用威尔逊定理的扩展来计算 A! mod P。扩展的表述为:如果 P 是一个合数,则有 A! ≡ (P-1)! * (A^(P-1/p1) mod P)^(p1-1) * ... * (A^(P-1/pm) mod P)^(pm-1) (mod P),其中 p1, p2, ..., pm 是 P 的所有质因数。

下面是一个用 Python 实现威尔逊定理扩展的例子:

def factorial_modulo_extended(a, p):
    if a >= p:
        return 0
    if a == 0:
        return 1
    fact = factorial_modulo_extended(p-1, p)
    for pi in prime_factors(p):
        fact *= pow(a, (p-1)//pi, p) + 1
        fact %= p
    return fact

def prime_factors(n):
    factors = []
    d = 2
    while d*d <= n:
        while (n % d) == 0:
            factors.append(d)
            n //= d
        d += 1
    if n > 1:
        factors.append(n)
    return factors

# 测试
print(factorial_modulo_extended(5, 7))  # 1
print(factorial_modulo_extended(10, 13))  # 11
总结

本文介绍了三种计算 A! mod P 的方法:直接计算、威尔逊定理和威尔逊定理的扩展。其中,直接计算是最简单的方法,但对于大的 A 会有溢出的风险;威尔逊定理可以处理质数情况,但对于合数需要使用扩展版。对于特别大的 A 和 P,还可以使用其他更高效的算法,例如 Pollard-Rho 算法。