-
快速幂的递归和非递归
- 递归(压栈弹栈花费空间更多些)
我们先来看看递推方程
1.>a^n = a^(n/2) * a^(n/2) , 当n为偶数时
2.>an=a(n-1)*a , 当n为奇数时
3>1 , 当n等于0时
这样最后的程序就很简单了. - 非递归
我们把a^b 中的b写成二进制形式,比如2^10,10的二进制形式为1010,那么 2^10= 2^0 *(2^2) * (2^0) *(2^8)
我们可以发现这样从小到大依次累加,每次是上一次的两倍,就像一颗树形结构一样,最后它的时间复杂度为O(logn)
#include<iostream>
using namespace std;
int pow(int m,int n)
{
if(n==0) return 1;
if(n%2!=0)
{
return m*pow(m,n-1) %MOD;
}else{
int temp=pow(m,n/2)%MOD; //注意这里的temp写的很有必要,如果最后返回的值pow(m,n/2)*pow(m,n/2),相当于没有进行优化,算法退化到o(n)的时间复杂度
return temp*temp%MOD;
}
}
int pow_(int m,n)
{
if(n==0) return 1;
int ans=1;
while(n)
{
if(n&1)
{
ans*=a;
}
a=a*a;
n>>=1;
}
return ans;
}
int main()
{
int res1=pow(2,7);
int res2=pow(2,8);
cout<<res1<<res2;
return 0;
}
这里"附赠一道题目",POJ2109,链接:http://poj.org/problem?id=2109
对于这样的a^b=c,且都是大数,已知a,c怎么求得b呢?
我们可以使用数学上的对数运算的方法来求(左边为底数,右边为真数):(loga b)^(-1)=(logb a),最重要的是下面的这个公式:
c ^ (1/a) ?= log a c,想明白这一点,这道题就很简单了,实际上也不简单,呜呜,我想了将近一个小时…这里不一定是等号,实际上是一个向上取整的过程.
#include <math.h>
#include <iostream>
using namespace std;
int main(void) {
double n , p;
while(cin >> n >> p) {
double tmp = pow(p, 1 / n); // p开n次方
int k = floor(tmp + 0.5); // 四舍五入(+0.5后向下取整)
cout << k << endl;
}
return 0;
}
2348

被折叠的 条评论
为什么被折叠?



