[[TOC]]
解释
现在我们需要求b a s e b base ^ b ba s e b ,显然最简单的方法就是执行b b b 次for循环,但如果b b b 很大,例如1 0 9 10^9 1 0 9 ,就会超时.
显然: ++任意一正整数都可以唯一的表示成若干个不重复的2的次幂的和++,也就是可以唯一的写成对应的二进制形态.
那么如果设b b b 在二进制状态下有k k k 位,设第i ( 0 ⩽ i < k ) i(0 \leqslant i < k) i ( 0 ⩽ i < k ) 表示成c i c_i c i ,c i ∈ 0 , 1 c_i \in {0,1} c i ∈ 0 , 1 ,那么b b b 可以表示成如下
b = c k − 1 2 k − 1 + c k − 2 2 k − 2 + ⋯ + c 0 2 0 (1)
b =c_{k-1} 2^{k-1} + c_{k-2} 2^{k-2} + \cdots + c_0 2^0
\tag 1
b = c k − 1 2 k − 1 + c k − 2 2 k − 2 + ⋯ + c 0 2 0 ( 1 ) 结合指数幂分配律: a m + n = a m × a n a^{m+n} = a^m \times a^n a m + n = a m × a n
a b = a c k − 1 2 k − 1 × a c k − 2 2 k − 2 + ⋯ + a c 0 2 0 (2)
a ^ b = a^{c_{k-1} 2^{k-1}} \times a^{c_{k-2} 2^{k-2}} + \cdots + a^{c_0 2^0} \tag 2
a b = a c k − 1 2 k − 1 × a c k − 2 2 k − 2 + ⋯ + a c 0 2 0 ( 2 ) 再根据幂乘方律: ( a m ) n = a m n (a^m)^n = a^{mn} ( a m ) n = a mn ,所以a 2 i = a 2 i − 1 ⋅ 2 = ( a 2 i − 1 ) 2 a^{2^i} = a^{2^{i-1} \cdot 2} = (a^{2^{i-1}})^2 a 2 i = a 2 i − 1 ⋅ 2 = ( a 2 i − 1 ) 2 ,也就是说a b a^b a b 是的相邻两项是"倍之"的关系.
又一个显然的数学常识,整数b b b 的二进制的位数有⌈ l o g 2 ( b + 1 ) ⌉ \lceil log_2^{(b+1)} \rceil ⌈ l o g 2 ( b + 1 ) ⌉ ,也就说a b a^b a b 最多有⌈ l o g 2 ( b + 1 ) ⌉ \lceil log_2^{(b+1)} \rceil ⌈ l o g 2 ( b + 1 ) ⌉ 个项.
代码模板
综上,可以写下面的代码.
template < typename T = long long >
T quick_pow ( T base, T b , T mod) {
T ans = 1 % mod;
for ( ; b; b>>= 1 )
{
if ( b & 1 )
ans = ans * base % mod;
base = base * base % mod;
}
return ans;
}
复制
题目