快速幂
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的二进制组成,再判断是否需要乘入答案。
这样一来,整个快速幂的优化便实现了。
若思路与代码有什么漏洞的话,欢迎指正!!!
以上是关于快速幂的主要内容,如果未能解决你的问题,请参考以下文章