快速幂

Posted beauty-of-wisdom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速幂相关的知识,希望对你有一定的参考价值。

快速幂 

  顾名思义,快速幂算法是对幂运算的一个加速优化,其算法框架基于分治算法(二分)之上。

  接下来,介绍两种优化方法。

·基本快速幂算法

  首先,给出传统求幂的代码:

#include<iostream>
using namespace std;

int main()
{
unsigned long long a,b;
cin >> a >> b;
if(b == 0) {
if(a==0){
cout <<"Wrong data!"<<endl;
return 0;
}
cout << 1 <<endl;
return 0;
}
unsigned long long x = a;
for(int i = 2;i <= b; ++i) {
a*=x;
}
cout << a <<endl;
return 0;
}

  以求2的12次方为例,在传统求幂代码中,计算2的12次方需要计算11次乘方。但实际上,我们可以先计算出2的平方的值,把计算过程转化为4x4x4x4x4x4的形式,减少了运算量。

  然而,我们还可以将4x4转化为2的4次方,计算过程写为16x16x16的形式。这样一来,我们只需计算2x2、4x4、16x16x16的值。整个过程只计算了4次。

  于是,我们以递归二分的形式得出基本快速幂算法,代码如下:

#include<iostream>
#include<cstdlib>
using namespace std;

long long a, b;

long long pow(int x, int y)
{
	if(y == 0)
	{
		if(x == 0)
		{
			cout << "Wrong Data!" << endl;
			exit(1);
		}
		return 1;
	}
	else if(y == 1) return x; 
	long long c = pow(x,y/2);
	if(b&1) return c*c*x;
	else return c*c;
}
int main()
{
	cin >> a >> b;
	cout << pow(a,b) <<endl;
	return 0;
}

·快速幂的位运算优化

  由二进制可知,一个数可以由2的次方的和表示,同理,我们可以将次方数b拆分为多个2的次方的和,以减少计算次数。同时,利用位运算中的 &、>> 进行优化加速,以提高效率。

                                  a11=a(2^0+2^1+2^3)

  如求a^11时,我们可以通过求a(2^0+2^1+2^3) 即求a、a^1、a^3 的值解决问题。

  至于如何实现上述过程,详见代码:

#include<iostream>
#include<cstdlib>
using namespace std;

long long a, b;

long long pow(int x, int y)
{
	if(y == 0)
	{
		if(x == 0)
		{
			cout <<"Wrong Data!"<<endl;
			exit(1);
		}
		return 1;
	}
	int base = x , ans = 1;
	while(y!=0)
	{
		if((y&1)!=0)
		{
			ans*=base;
		}
		base *= base;
		y >>= 1;
	}
	return ans;
}
int main()
{
	cin >> a >> b;
	cout << pow(a,b) <<endl;
	return 0;
}

  可知,base初始为a^(2^0),再次base累乘时,base都会变成a^(2^1),推导计算过程可知,每次base累乘,都会导致base的指数的指数(base^(2^n)中的n)增加1。

  那么,我们同时利用>>右移运算符,从二进制的角度判断b的二进制组成,再判断是否需要乘入答案。

  这样一来,整个快速幂的优化便实现了。

技术分享图片

  若思路与代码有什么漏洞的话,欢迎指正!!!

 

以上是关于快速幂的主要内容,如果未能解决你的问题,请参考以下文章

矩阵快速幂

快速幂

快速幂

快速幂乘法&快速幂取余

快速幂和慢速乘

快速幂解法