快速幂

快速幂

个人博客:https://sgeekioi.github.io/2019/07/31/fastpower/#more

【介绍】

顾名思义,快速幂就是快速算底数的n次幂。其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高。

【描述】

计算a的n次方就是将n个a乘起来 a n = a × a × a . . . × a ⎵ n个a a^n = \underbrace{a \times a \times a...\times a}_{\text{n个a}} an=na a×a×a...×a。但是,当n的值特别大的时候,这种累乘的方法就不合适了。不过,由结合律我们知道 a b + a c = a b c , a b × a b = a 2 b = a b 2 a^b + a^c = a^{bc} , a^b \times a^b= a^{2b} = {a^b}^2 ab+ac=abc,ab×ab=a2b=ab2。二进制取幂的想法是,我们将取幂的任务按照指数的二进制表示来分割成更小的任务。我们来举个例子

11的二进制数为 1011。 对进制不太理解的戳这里

3 11 = 3 1011 = 3 8 ⋅ 3 2 ⋅ 3 1 3^{11} = 3^{1011} = 3^8 \cdot 3^2 \cdot 3^1 311=31011=383231

上面这个算式是怎么来的呢。看下面

3 1 = 3 2 0 = 3 3 2 = 3 2 1 = 9 3 8 = 3 2 3 = 6561 3^1 = {3^2}^0 = 3 \\ 3^2 = {3^2}^1 = 9 \\ 3^8 = {3^2}^3 = 6561 31=320=332=321=938=323=6561

也就是为了计算 3 11 3^{11} 311,我们只需要将二进制位对应为1的整系数幂乘起来就行了:

3 11 = 3 × 9 × 6561 = 177147 3^{11} = 3 \times 9 \times 6561 = 177147 311=3×9×6561=177147

将上述过程说的形式化一些,如果把n写作二进制为 ( n 1 n t − 1 … n 1 2 1 + n 0 2 0 ) (n_1n_{t-1}…n_12^1+n_02^0) (n1nt1n121+n020),那么有:

n = n t 2 t + n t − 1 2 t − 1 + … + n 1 2 1 + n 0 2 1 n=n_t2^t+n_{t-1}2^{t-1}+…+n_12^1+n_02^1 n=nt2t+nt12t1++n121+n021
其中 n ϵ 0 , 1 n \epsilon 0,1 nϵ0,1 。那么就有

a n = ( a n t 2 t + … + n 0 2 0 ) = a n 0 2 0 × a n 1 2 1 × … × a n 0 2 0 a^n=(a^{n_t2^t+…+n_02^0}) \\ =a^{n_02^0} \times a^{n_12^1} \times … \times a^{n_02^0} an=(ant2t++n020)=an020×an121××an020

根据上式我们发现,原问题被我转换成了形式相同的子问题的乘积,并且我们可以在常数时间内从 2 i 2^i 2i项推出 2 i + 1 2^{i+1} 2i+1项。这个算法的复杂度是 O ( l o g 2 n ) O(log_2n) O(log2n)的。

##【代码实现】

递归方法

public double power1(double a, int n) {
        if (n == 0) {
            return 1;
        }
        double res = power(a,n/2);
        if((n%2)==1){
            return res * res * a;
        }else{
            return res * res;
        }
    }

非递归式

它在循环的过程将二进制为1时对应的幂累乘到答案中。尽管两者的理论复杂度相同,但第二种在实践过程中的速度会比递归式更快的,因为递归会重复运算花费一定开销。

public double power2(double a,int n){
        double res = 1;
        while (n>0){
            if((n&1)==1){
                res*=a;
            }
            a*=a;
            n>>=1;
        }
        return res;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值