快速幂理解

  听人介绍这算法很神奇,时间复杂度减很快我就来学学啦。

  首先来个题干:求A的B次方的最后三位数。

  最基础最普通的想法就是直接循环挨个求然后对1000取模输出,但是有一个问题就是当次方数很大时long long也无法存下最后结果,溢出结果会为0。

  进阶版想法就是我昨天刚学的同余定理:https://www.cnblogs.com/zoeyzy/p/14290815.html 参见我的博客

  用(a * b) % p = (a % p * b % p) % p这个公式边取模边算确实可以得到最后结果:

long long normalPower(long long base,long long power){
    long long result=1;
    for(int i=1;i<=power;i++){
        result=result*base;
        result=result%1000;
    }
    return result%1000;
}

  但是仍然有一个时间复杂度的问题,所以就有了下面更高级的算法:

  比如要算2的100次方,可以分解为4的50次方,一下子时间就少了近乎一半,再变一变就是16的25次方。

long long fastPower(long long base, long long power) {//base为底数,power为指数
    long long result = 1;
    while (power > 0) {
        if (power % 2 == 1) {
            result = result * base % 1000;
        }
        power = power / 2;
        base = (base * base) % 1000;
    }
    return result;
}

  注意假如指数是奇数的话就-1再在下一次循环时除以2,而此时最后结果result应该乘以一次base,时间复杂度就降了非常非常多。

  最终版:令我震惊的是这个题居然还可以用位运算,虽然学长讲过一遍但时间久远加没练过题我已经记不太清了=…=

  首先可以用power&1判断power的奇偶,得到power二进制时最后一位数字,如果是0则是偶数,是1则是奇数。然后运算power = power / 2时,也可以用位运算,将power的二进制往右边移一位就是它的一半。

  上代码:

#include<stdio.h>
long long fastPower(long long base, long long power) {
    long long result = 1;
    while (power > 0) {
        if (power & 1) {//此处等价于if(power%2==1)
            result = result * base % 1000;
        }
        power >>= 1;//此处等价于power=power/2
        base = (base * base) % 1000;
    }
    return result;
}

int main()
{
    long long base,power;
    scanf("%lld %lld",&base,&power);
    printf("%lld",fastPower(base,power));
    return 0;
 } 

  发现小学期项目完成后对函数没那么抵触了^^,并不会头皮发麻或者手足无措了,事实证明多写写是很有必要的。

  与看见博客的你共勉。

 

posted @ 2021-01-18 23:43  Zoey的小窝  阅读(106)  评论(0)    收藏  举报