快速幂以及扩展的矩阵快速幂应用场景比较常见。
幂运算a的n次方,即n个a相乘,快速幂就是高效的算出结果。当n很大时,很多时候都不能处理,一是数字太大,二是计算时间太长。因此对于这种问题便产生了快速幂的运算。
具体思路:
假设要求a的11次方,先把a的11次方分解为a的八次方,a的二次方,a的零次方的积。
再接下来,a1 * a1 = a2,a2 * a2 = a4,a4 * a4 = a8,都是2的倍数,产生的ai都是倍乘关系,逐渐递推就可以了。
那么在如何将11分为8+2+1的问题上,使用数字的二进制即可。将11转为二进制,二进制中每一位的权值都是低一位的两倍,对应的ai就是倍乘的关系,11的二进制为1011 = 1 * 23 + 0 * 22 + 1 * 21 + 1 * 20 ,所以只需要将n用二进制处理就可以了。
再回想其中的0的跳过计算,在这里可以使用位运算即可实现。
- n & 1,取n的最后一位,判断是否需要跳过
- n >> 1,把n右移一位,将刚处理过的最后一位去掉
在实现了上面的步骤下快速幂的具体思路已经构建完了,直接放代码即可:
int quickpow(int n, int a)
{
int base = n;
int res = a;
while (n)
{
if (n & 1)
res *= base;
base *= base;
n >>= 1;
}
return res;
}
如果产生的数据仍然太大,则可以使用取模运算,在res * base 和 base * base 的时候进行取模运算即可。
const int mod = 10000;
int quickpow(int n, int a)
{
int base = n;
int res = a;
while (n)
{
if (n & 1)
res = (res * base) % mod;
base = (base * base) % mod;
n >>= 1;
}
return res;
}