Loading

大数求余

大数求余问题: 在仅使用 int32 类型存储的前提下, 计算 \(x^a\ \text{mod}\ p\) (即 \(x^a\ \%\ p\)).

基本的运算规则: \((xy)\ \%\ p = [(x \ \% \ p)(y \ \% \ p)] \ \% \ p\)

循环求余

\(x < p\) 时,

\[x^a \ \% \ p = [(x^{a-1} \ \% \ p)(x \ \% \ p)] \ \% \ p = [(x^{a-1} \ \% \ p)x]\ \% \ p \]

利用此公式, 可以通过循环操作依次求 \(x^1, x^2,\cdots, x^{a-1}, x^a\)\(p\) 的余数

# 求 (x^a) % p -- 循环求余法
def remainder(x, a, p):
    rem = 1
    for _ in range(a):
        rem = (rem * x) % p
    return rem

时间复杂度为 \(O(a)\)

快速幂

\[x^a \ \% \ p = (x^2)^{a/2} \ \% \ p = (x^2 \ \% \ p)^{a/2} \ \% \ p \]

具体要看 \(a\) 的奇偶性:

\[x^a \ \% \ p = \left\{\begin{matrix} (x^2 \ \% \ p)^{a//2} \ \% \ p & , a 为偶数 \\ [x(x^2\ \%\ p)^{a//2}] \ \% \ p &, a 为奇数 \end{matrix}\right. \]

时间复杂度为 \(\log a\) .

十进制正整数 \(a\) 的二进制形式为 \(b_m\cdots b_2b_1b_0\) , 则 \(x^a = x^{2^{m}b_m} \times \cdots \times x^{2^1 b_1}\times x^{2^{0}b_0}\). 计算 \(x^1, x^2, x^4, \cdots , x^{2^m}\) 的值:

# 求 (x^a) % p -- 快速幂求余
def remainder(x, a, p):
    rem = 1
    while a > 0:
        if a & 1: rem = (rem * x) % p
        x = (x * x) % p
        a >>= 1
    return rem
posted @ 2025-10-06 13:48  Chase_Tsai  阅读(5)  评论(0)    收藏  举报