平方求幂取余,模幂,快速幂取余数
以下的内容来自 维基百科:模幂
从右到左的二位算法
第三种方法结合了第二种算法和平方求幂原理,使所需步骤大大减少,同时也与第二种方法一样减少了内存占用量。
首先把\(e\)表示成二进制,即:
\[e = \sum_{i=0}^{n-1} a_i 2^i
\]
此时\(e\)的长度为\(n\)位。对任意\(i\)(\(0\leq i < n\)),\(a_i\)可取0或1任一值。由定义有\(a_{n-1}=1\)。
\(b^e\)的值可写作:
\[b^e = b^{\left( \sum_{i=0}^{n-1} a_i 2^i \right)} = \prod_{i=0}^{n-1} \left( b^{2^i} \right) ^ {a_i}
\]
因此答案\(c\)即为:
\[c \equiv \prod_{i=0}^{n-1} \left( b^{2^i} \right) ^ {a_i}\ (\mbox{mod}\ m)
\]
伪代码
下述伪代码基于布魯斯·施奈爾所著《应用密码学》。其中base
,exponent
和 modulus
分别对应上式中的 \(b\),\(e\) 和 \(m\)。
function modular_pow(base, exponent, modulus)
if modulus = 1 then return 0
Assert :: (modulus - 1) * (modulus - 1) does not overflow base
result := 1
base := base mod modulus
while exponent > 0
if (exponent mod 2 == 1):
result := (result * base) mod modulus
exponent := exponent >> 1
base := (base * base) mod modulus
return result
注意到在首次进入循环时,变量base
等于\(b\)。在第三行代码中重复执行平方运算,会确保在每次循环结束时,变量base
等于\(b^{2^i} \bmod m\),其中\(i\)是循环执行次数。