快速幂

 

原理分析

       求a^n的值,按照传统的写法就是用一个数ans = 1 ,乘n次a,这样的时间复杂度为O(n),而快速幂算法是基于二进制,可以将时间复杂度将为log(n)

       举个例子,我们要求3^11,我们可以写成  3^(2^3+2^1+2^0),拆开后就是3^(2^3) = 3 ^ 8 、3^(2^1)=3^2 、 3^(2^0) = 3^1 , 这样看来,如果我们只计算这三个的乘积,岂不是只需要计算3次?而且这三个数之间是很有规律的,

       比如  (3^1)^2 = 3^2 , ( (3^2)^2) ^2 = 3 ^8,就是对一个数不断的取二次幂,由于任意整数都可以用二进制的数来表示,也就是说我们可以将任意整数拆解成3^(2^3+2^1+2^0)这样的形式(为了方便,我们将要求的数记作a^n) , 而对于2^k是否出现,取决于n在二进制表示下第k+1位数是否为1 。 为了更加清晰的解释,我们分析一下 11 这个数,其二进制的表示形式为 1011 , 对应出现了第4 , 2 , 1 位数,于是与之对应的2^3  , 2^1 , 2^0 也就出现了。

       上面我们解释了任意整数都可以写成  a ^ (2 ^ m + 2 ^ k .... )的形式,而且对于 m+ 1= k 的情况时,存在

  (a^(2^m)) ^ 2 = a^(2^m+1) = a^(2^k) , 再根据2^k的出现规律,我们只需要将2^k从 k = 0 开始,不断地取二次幂,如果n在二进制下的第k+1位数为1,我们用ans记录当前的值,这时候将a(2^k)乘入ans 中,最后我们就得到了最终的答案

代码区

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;

ll pow_fast(ll a, ll n)
{
	ll ans = 1;
	while (n != 0)
	{
		if (n & 1 != 0)ans =ans*a;
		a = a * a;
		n >>= 1;
	}
	return ans;
}

int main()
{
	cout << pow_fast(2, 5) << endl;
	return 0;
}

 

posted @ 2019-03-28 12:57  winter-bamboo  阅读(170)  评论(0编辑  收藏  举报