虽然快速幂的思想比较简单, 而且之前也复习过一遍了, 但是刚才写代码的时候还是重新推了一遍才想起来怎么写, 所以这里写(水)一篇 blog 来增强理解.
简介
快速幂是用来快速求解 的一种算法.
分析
当 b 不是很大的时候, 显然我们可以暴力求解 , 这时复杂度是 , 可是当 b 的数量级很大的时候怎么办呢?
这个时候就需要用到快速幂算法了.
当 b 为偶数时, , 当 b 为奇数时, .
我们要是知道 就可以很快求出 了, 这时很容易想到递归求解 , 毕竟这种情况下递归计算 的复杂度是 的.
递归的实现方法很简单, 这里不再赘述.
我们考虑非递归式的写法.
在递归式写法中, 每递归一次, a 的次数就会翻一倍, 一共递归了 次, 因此我们在循环过程中每次 a *= a
和 b >>= 1
即可, 但是如果 b 为奇数时需要再乘以原始的 a, 而此时 a 的值已经变了怎么办?
我们从一些简单的例子入手.
考虑 和 的情况.
在 的情况下, 我们需要在第一次循环时乘以 a , 此时 a 的值没有变, 之后我们再令 a 自乘.
在 的情况下, 第一次循环时的情况与 的相同, 没有影响, 第二次循环时, 对于先前分出来的 2 个 我们都要乘一次 a , 也就是需要乘两次 a , 相当于乘以 , 正好是此时 a 变化一次后的值.
同理, 我们可以看出, 当 b 更大, 需要乘 a 的次数更多的时候, 假设当前是第 k 次循环, 那么我们已经将 拆成了 个 (当然还要算上奇数情况下多乘的 a )的形式, 当进入第 k + 1 次循环时, 若 b 为奇数, 这 个 都要乘一个 a , 相当于乘上了一个 , 而可以发现这正好是当前 a 经过 k 次自乘后的值, 因此我们只需每次判断 b 的奇偶性, 若为奇数, 就 ret *= a
即可.
代码
1 | typedef long long ll; |
Author: f1a3h
Permalink: https://blog.rbkou.me/Algorithm/quickpow/
文章默认使用 CC BY-NC-SA 4.0 协议进行许可,使用时请注意遵守协议。
Comments