了解快速幂算法(基础)

目录

 

快速幂

原理

例子

算法实现

算法优化

第一次优化

第二次优化


 

快速幂

顾名思义,快速幂就是快速计算底数的n次幂。它的时间复杂度为\\O(log_2 N),而直接用for循环一次次计算的时间复杂度为\\O(N)

 

原理

通过将指数拆分成几个因数相乘的形式,来简化幂运算。具体就是每一步都把指数分成两半(在可分的情况下),而相应的底数做平方运算。这样不仅能把非常大的指数给不断变小,还能节省计算机计算所消耗的时间。下面我们看个简单的例子。

 

例子

计算:2^{10} = 2\times2\times2\times2\times2\times2\times2\times2\time2\times2\times2  ———— ①

 

用一般的for循环计算这个值得话需要循环10次才能计算出结果,但如果我们进行一下处理:

2^{10}=(2^5)^2=2^{2\times5}=4^5                    //此时它的指数由10降低为5,则连带上一次2\times2运算,我们的计算次数就变为6次了

 

这样处理的话在进行比较大的幂运算时会节省很多时间,比如说计算2^{100000}时,底数先进行一个平方运算就能把指数由100000变为50000,节省了50000次for循环的时间。

 

我们再接着处理4^5,这是后我们发现5不能被分成两半了,因为5是奇数。
但我们可以把它处理为这样:4^4\times4^1,这样我们又可以接着对4^4进行分半:4^{4}=4^{2\times2}=16^{2},此时式子①就可以表示为2^{10}=16^{2}\times4^{1}。此时计算次数由6变为了5

我们接着进行分半工作直到指数都为1。最后①变为:2^{10}=256\times4
这样如果用计算机计算幂很大的数时就可以快速幂算法简化计算,加快运算时间。

 

算法实现

//快速幂函数
long long fastPower(long long base, long long power) {
    long long result = 1;              //result记录算出的结果
    while (power > 0) {                //指数变为1时停止

        //如果指数power为偶数
        if (power % 2 == 0) {
            power = power / 2;         //把指数缩小为一半
            base = base * base;        //底数变大成原来的平方
        } 

        //如果指数为奇数
        else {
            power = power - 1;         //把指数减去1,使其变成一个偶数
            result = result * base;    //此时记得要把指数为奇数时分离出来的底数的一次方收集好
            power = power / 2;         //此时指数为偶数,可以继续执行分半操作
            base = base * base;
        }
    }
    return result;//返回结果
}

 

算法优化

第一次优化

我们知道在C/C++语言中,如果赋一个小数(如1.5)的值给整型的话,整型只会记录小数点前的整数。
例如:

long long i;
i = 3 / 2;
printf("%ll",&i);//输出的结果为1

那么我们就可以根据这个来简化一下while循环里的语句。
 

long long fastPower(long long base, long long power) {
    long long result = 1;
    while (power > 0) {

        //如果power是奇数,把指数为奇数时分离出来的底数的一次方收集好
        if (power % 2 == 1) {
            result = result * base;
        }

        //power = power / 2;这句语句在遇到power为奇数时,相当于之前power - 1再除于2赋的值;
        //在遇到power是偶数时,就相当于这句语句
        power = power / 2;
        base = base * base;//把base^2计算出来
    }
    return result;
}

第二次优化

C语言中有“位运算”,它是比“算术运算”更底层的操作,所以如果我们使用“位运算”代替“算术运算”就能在更少时间内得到结果。
“位运算”都是二进制操作。

说明:

&为与运算符,1&1 = 1、1&0 = 0、0&1 = 0.

把一个数化为二进制数表示,那么二进制的最后一位(最右边那位)如果是1,那么这个数为奇数;如果为0,那就为偶数。比如说5的二进制表示为\left ( 101 \right )_2,10的二进制表示为\left (1010 \right )_2。那么如果我们把一个数与1进行与运算&就能得到那个数的最右边那位数,由此就可以判断它是奇数还是偶数了。

10:(1010) & 1:(0001)

    1010
&   0001
    0000 —— 即0
-------------------------------------------------------------------------------------------
5:(101) & 1:(001)

    101
&   001
    001 —— 即1

>>为右移运算,右移一位相当于除于2,右移两位相当于除于2^{2} 


所以再次优化的代码为:

long long fastPower(long long base, long long power){
    long long result = 1;
    while(power){                      //当power等于0时停止循环

        if(power&1)                    //如果power的当前末位为1
            result = result * base;    //result乘上当前的base

        base = base * base;            //自乘
        power = power >> 1;            //power往右移一位,相当于power = power / 2
    }
    return result;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值