ModularExponentiation 模幂运算

问题

给定正整数b,e,mb, e, m,求:

c=be(modm)c = b^{e} \pmod{m}

简单算法

按照次方运算的原理,初始化c=1c = 1,重复ee次:

c=(c×b)modmc = (c \times b) \bmod m

即为所求,该算法的时间复杂度为O(e)O(e)

二进制算法

根据二进制可知,任何正整数ee都可以用nn22的次方和来表示:

e=i=0n1ai2ie = \sum_{i=0}{n-1} a_{i} \cdot 2^{i}

其中nn是正整数ee中1的数量,aia_{i}要么为00要么为11,且an1=1a_{n-1} = 1。因此beb^{e}可以转换为:

be=b(i=0n1ai2i)=i=0n1(b2i)aib^{e} = b^{(\sum_{i=0}{n-1} a_{i} \cdot 2^{i})} = \prod_{i=0}{n-1} (b^{2^{i}})^{a_{i}}

因此模幂运算转换为:

ci=0n1(b2i)ai(modm)c \equiv \prod_{i=0}{n-1} (b^{2^{i}})^{a_{i}} \pmod{m}

计算每个元素(b2i)ai(b^{2^{i}})^{a_{i}},若ai=0a_{i} = 0则结果必然为11,不必计算,若ai=1a_{i} = 1则需要2i2^{i}次乘法,即时间复杂度为O(2i)O(2^{i})(其中0in10 \leq i \leq n-1)。

该算法的时间复杂度为O(i=0n12iai)O(\sum_{i=0}{n-1} 2^{i} \cdot a_{i})

求正整数ee中所有为1的bit位的方法,与本书第三章DataStructure中FenwickTree一节使用的方法一样,不再赘述。

快速求幂算法

快速求幂算法基于以下公式:

be={1e=0be=1(b×(b2)e12)modmbisodd((b2)e2)modmbisevenb^e = \begin{cases} 1 & e = 0 b & e = 1 (b \times (b^2)^{\frac{e-1}{2}}) \bmod m & b is odd ((b^2)^{\frac{e}{2}}) \bmod m & b is even \end{cases}

该算法的时间复杂度为O(log2e)O(log_2 e)

源码

ModularExponentiation.h

ModularExponentiation.cpp

测试

ModularExponentiationTest.cpp

Last updated