快速幂
简介
快速幂是能快速计算一个幂的方案,他可以作用于所有满足结合律、封闭性的二元运算,即半群
定义
不妨假设这个二元运算为\(\circ\),两个元素进行运算为\(x\circ y\),当\(xy\)同为\(x\)时,不妨设\(x^2=x\circ x\), 同样的\(x^1=x\), 当然\(x^0=e\), 还有\(x^k=x^{k-1}\circ x\)
快速幂核心思想
在半群中,只要\(k=u+v\)一定有\(x^k=x^u\circ x^v\).
所以我们可以把k看作一个二进制数,把\(x^k\)分解为\(x^{2^{p_1}}\circ x^{2^{p_2}}\circ x^{2^{p_3}}\circ \circ \circ x^{2^{p_n}}\)
这里最多分解为\(\log_2(k)\)个元素,而且每个元素可以由前k个元素获取,所以只需要进行\(log_2(k)\)次二元计算即可的到最终答案。
代码
1 | T qpow(T a,int k){ |
加法模群快速幂
在加法模群中,getE()
定义为0,因为任何数加上0得到自身。binaryOp
为二元运算\(binaryOp(x,y)=(x+y)\mod p\)。
乘法模群快速幂
在乘法模群中,getE()
定义为1,因为任何数乘以1得到自身。binaryOp
为二元运算\(binaryOp(x,y)=(x\cdot y)\mod p\)。
矩阵乘法模群快速幂
在矩阵乘法模群中,getE()
定义为矩阵的单位元,即对角线全为1的对角矩阵。binaryOp
为普通矩阵模乘。
无理数乘法快速幂
很多时候我们需要用到无理数,即设一个无理数\(y=\sqrt{(c_1)}\cdot x_1+x_2\), 其中\(x\)为变量,\(c\)均为常量,一个无理数可以被唯一标识为一个二元组\((x_1,x_2)\),
这时候单位元是getE()
=\((0,1)\),binaryOp
为普通无理数乘法。
置换群快速幂
在置换中,单位元为\(h=\begin{pmatrix} 1 & 2 & 3 &... &n\\ 1 & 2 & 3 &... &n \end{pmatrix}\) ,binaryOp
为普通置换乘法。
十进制快速幂
有的时候,给你的k是一个10进制大数,由于我们朴素的快速幂需要使用二进制的k(后面有移位),所以会遇到一些麻烦。
当然,最简单的就是直接分解为十进制乘法。
\(x^k=x^{10^{p_1}}\circ x^{10^{p_2}}\circ x^{10^{p_3}}\circ \circ \circ x^{10^{p_n}}\)
道理都是一样的。这里最多分解出\(\log^{10}(k)\)个元素,每个\(x^{10^1}\)可以从前一项直接运算推导。最多进行\(\log^{10}(k)\)次计算
代码
矩阵快速幂
1 | typedef long long ll; |
十进制快速幂
1 |
|