本文已参与「新人创作礼」活动,一起开启掘金创作之路。
快速幂是分治思想的一个典型的应用。 最大的特点是能够快速计算出a的b次方是多少。原理如下: 例如:计算 2 的 5 次方和 2 的 6 次方
传统的计算方式是使用循环,每次都去乘以底数本身,这样虽然很直观,但是当次数多起来的时候,需要通过很多次循环才能达成目标,例如2的5次和6次,需要分别进行5次和6次循环,而如果使用快速幂的话,循环次数则降低到3次,若是2的16次方,则可将传统的16次循环降低到5次循环
首先从 1 开始(因为非0的数乘以1之后还是本身),拿计算 2 的 5 次方来说,通过不断地乘以底数可以快速的让指数翻倍,进行成倍的增长。拿上面的例子来说,从 1 开始时,先暂时设一个 变量 ans 存放最终答案。一开始 ans 为 1 ,然后让 ans = 2 * 2;此时 ans 为 4 也就是 2 的 2次方此时,然后重复此操作,但是遇到指数为奇数时应该多乘以一个底数,同时指数也应该除以 2 ,取整,忽略小数部分
至于原因则是:同底数幂相乘,底数不变,指数相加,而一个数平方之后,相当于指数乘以2
为什么指数为奇数的时候要多乘以一个数呢? 指数在除以二取整之后,会忽略小数部分,而正常情况下这个是有一次方的
在模拟一次过程后会发现随着指数的下降,底数的乘积也在不断的增大,所以它们相互抵消掉了。用我的不标准语言表示就是 a 的 b 次方等于 a 的 2/b次方 乘以a 的 2/b次方(中间的除号是分数线),a 的 c 次方 = a * a,a 的 b 次方等于 a 的 c 次方,b 减小了,c 增大了。 计算 2 的 6 次方的时候也是同样的原理。
下面是代码
#include <iostream>
using namespace std;
long long k(long long a,long long b)
{
long long base = a; //保存底数
a = 1;
while (b > 0)
{
if (b & 1 != 0) //判断指数b是否为奇数
{
a = base * a;
}
base = base * base;//底数相乘
b = b >> 1; //右移,相当于除以2
}
return a;
}
int main()
{
ios::sync_with_stdio(false);
long long n,d;
long long ans;
cin >> n >> d;
ans = k(n,d);
cout << ans << endl;
return 0;
}