..
AcWing 89. a^b
题目链接:89. a^b - AcWing题库
如果 $b$ 在二进制表示下有 $ k $ 位,其中第 $i(0 \le i < k)$ 位的数字是 $c_i$ ,那么:
\[b = c_{k - 1} 2^{k - 1} + c_{k - 2} 2^{k - 2} + \cdots + c_{0} 2^{0}\]于是:
\[{a^b} = a^{c_{k - 1} * 2^{k - 1}} * a^{c_{k - 1} * 2^{k - 1}} * \cdots * a^{c_0 * 2^0}\]因为 $k = \lceil{\log_2(b + 1)}\rceil$ ,所以上式乘积项的数量不多于 $\lceil{\log_2(b + 1)}\rceil$ 个。
又因为:
\[a^{2^i} = (a^{2^{i - 1}})^2\]所以很容易通过 $k$ 次递推求出每个乘积项,当 $c_i = 1$ 时,把该乘积项累积到答案中。
b&1
运算可以取出 $b$ 在二进制表示下的最低位b>>1
运算可以舍去最低位
在递推的过程中将二者结合,就可以遍历 $b$ 在二进制表示下的所有数位 $c_i$ 。
在循环到 $i$ 次时,变量 $a$ 中存储的是 $a^{2^i}$,若 $b$ 该位为 $1$,则把此时的变量 $a$ 累计到答案 ans
中。
在 C++ 语言中,两个数值执行算数运算时,以参与运算的最高数值类型为基准,与保存结果的变量类型无关。
虽然两个 32 位整数的乘积可能超过 int
类型的表示范围,但是 CPU 只会用 1 个 32 位寄存器保存结果,造成越界现象。
因此,我们必须把其中一个数强制转换成 64 位整数类型 long long
参与运算,从而得到正确的结果。
最终对 $p$ 取模以后,执行赋值操作时,该记过会被隐式转换成 int
存回 ans
中。
整个算法的时间复杂度为 $\mathcal{O}(\log_2b)$。
完整代码:a^b.cpp