zoukankan      html  css  js  c++  java
  • 让幂运算更效率——快速幂

      在日常解决问题的过程中,我们常常会遇到求ab类似的问题,对于这种问题,我们一般的解决方法就是最朴素的方法就能解决,它的时间复杂度为O(b)。
    1 int power(int a,int b)    //求a的b次方
    2 {
    3     int i,ans=1;
    4     for(i=0;i<b;i++)
    5         ans*=a;
    6     return ans;
    7 }

    但是对于某些题目,当b的数据变大的时候,可能就会超时,这时候我们就需要用快速幂来优化我们的程序了。

    一、快速幂
    快速幂的原理来自于十进制二进制相互转换的加权系数法,对于任意一个十进制数,我们可以把它写成2k1+2k2+2k3+…+2kn+…(k=0,1,2…),继而转化为二进制,如10=21+23=(1010)2。那么对于ab的次数b来说,也是如此。我们可以把b拆成2k1+2k2+2k3+…+2kn+…(k=0,1,2…),那么ab就变成了a(2^k1+2^k2+2^k3+…+2^kn+…)(k=0,1,2…),继而可以化成a2^k1×a2^k2×a2^k3×…×a2^k1。这样一来,我们就把原来的时间复杂度O(b)压缩到O(log2b),这是一个很可观的改进。
    怎么用代码来实现呢?这里我们需要用到两个位运算&和>>,其中&是按位与,我们在代码中用(n&1)来判断n的二进制最后一位是不是1。n>>1的作用是二进制数左移一位,效果等同于除以2,但是时间要比除以2稍快。
    综上,我们就可以得到快速幂的实现代码了。
     1 long long fastpow(long long n,long long multi)
     2 {
     3     long long ans=1,base=n;
     4     while(multi)
     5     {
     6         if(multi&1) ans=(ans*base);
     7         base=(base*base);
     8         multi>>=1;
     9     }
    10     return ans;
    11 }

    但是在实际解题中很多情况下进行不了几次幂运算就会溢出,所以常常会让我们取模,下面我们来解决这个问题。

    二、快速幂取模
    求解快速幂取模的问题并不需要对算法做太多的改动,在乘运算时加上取模即可,但要注意取模尽量要考虑全面,因为不一定什么地方就会爆掉了。
    代码如下:
     1 long long fastpow(long long n,long long multi,long long mod)
     2 {
     3     long long ans=1,base=n;
     4     while(multi)
     5     {
     6         if(multi&1) ans=(ans*base)%mod;
     7         base=(base*base)%mod;
     8         multi>>=1;
     9     }
    10     return ans%mod;
    11 }

    三、矩阵快速幂

    (施工中orz)

    四、相关题目
    1.快速幂例题  Luogu P1226
    代码:
     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 long long mod,n,multi;
     6 
     7 long long fastmulti(long long n,long long multi,long long mod)
     8 {
     9     long long ans=1,base=n;
    10     while(multi)
    11     {
    12         if(multi&1) ans=(ans*base)%mod;
    13         base=(base*base)%mod;
    14         multi>>=1;
    15     }
    16     return ans%mod;
    17 }
    18 
    19 int main()
    20 {
    21     scanf("%lld%lld%lld",&n,&multi,&mod);
    22     long long ans;
    23     ans=fastmulti(n,multi,mod);
    24     printf("%lld^%lld mod %lld=%lld",n,multi,mod,ans);
    25     return 0;
    26 }
    Luogu P1226

    Author : Houge  Date : 2019.6.2

    Update log : 

  • 相关阅读:
    解决PKIX:unable to find valid certification path to requested target 的问题
    Linux 上的常用文件传输方式介绍与比较
    用VNC远程图形化连接Linux桌面的配置方法
    红帽中出现”This system is not registered with RHN”的解决方案
    linux安装时出现your cpu does not support long mode的解决方法
    CentOS SSH配置
    es6扩展运算符及rest运算符总结
    es6解构赋值总结
    tortoisegit安装、clon、推送
    es6环境搭建
  • 原文地址:https://www.cnblogs.com/CSGOBESTGAMEEVER/p/10964209.html
Copyright © 2011-2022 走看看