快速幂运算

179 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

昨天刚刚学了快速幂运算来加快幂运算,即a^x^,来总结一下 我们最常用的幂运算是,使用一个循环语句来控制循环乘或者直接使用库函数pow(int a,int n)来实现幂运算。

使用循环语句来进行幂运算,时间复杂度是O(n) 再进行网上查询了解到pow库函数的时间复杂度会比O(n)还大 了解链接为www.cnblogs.com/zhanghuaye/… 所以我们使用一种新的算法来解决超时问题

快速幂运算 快速幂运算实际上是用了二分的思想,不过二分法还没自学到那,就直接和你们说原理了 比如a^56^ ,我们如果不一个一个a相乘的话,怎么解决算才会减少时间呢,在我们实际运算一个幂运算的时候,给你一个2^8^,你是不是会进行2^4^ *2^4^来算2的8次方

不会吧不会吧真的还有人一个一个乘来算出2的8次方叭!

重新回到正题,a^56^ = (a^28^)^2^ = ((a^14^)^2^)^2^= ((a^7^)^2^)^2^)^2^ ,到奇数的时候怎么办? a^7^ = a^(3+3+1)^=(a^3^)^2^ * a,直到化到a,这样算下来时间复杂度就是O(logn),明显大大缩短了时间。

接下来敲一下代码 quick pow简称qp

int qp(int a,int n){
	int ans =1;
	while(n){
		if(n&1) ans *=a;
		a*=a;
		n>>=1;
	return ans;
}

这就是快速幂的代码,就这么短就缩短了大部分时间 接下来说一下代码细节 这里是运用了二进制转换来达到代码简便。

比如10的二进制为1010,计算2^10^的时候可以如下计算

我们知道2^10^ =2 (2^0^*0+2^1^*1+2^2^*0+2^3^*1) 所以计算a^n^的时候也一样 化为二进制的好处在于 可让a=a * a一直执行,当取到n的二进制不为0的时候就进行乘进去。

n&1的意思是 n的二进制和1进行 位与预算 插入一个位与预算的知识,比如10和1位与运算,10的二进制为1010,1的二进制就是1,位与运算的规则是,每个位置上一一对应,若同为1,则为1,如以下: 1010 0001 —— 0000 一个整数和1进行位与运算,即是取这个整数二进制的最后一位数,再配合右移运算符>>便可取完整个整数的二进制每个位数。

最后当n>>1 =0的时候结束循环,即可求得a^n^.