• 算法疑难(c++实现)---1、快速幂


    算法疑难(c++实现)---1、快速幂

    一、总结

    一句话总结:

    比如在求a^11的时候,快速幂就是利用11的二进制1011,也即11=2º×1+2¹×1+2²×0+2³×1=1+2+8,将a^11转化为a^1*a^2*a^8,从而用O(logn)的时间复杂度求解
    #include <iostream>
    using namespace std;
    
    int pow(int a,int n){
       int ans=1,base=a;
       while(n){
           if(n%2==1) ans=ans*base;
           base=base*base;
           n=n/2;
       }
       return ans;
    }
    
    int main(){
        cout<<pow(2,22)<<endl;
        return 0;
    }

    1、快速幂取模的原理?

    根据同余定理,我们知道,(a*b)%m=((a%m)*(b%m))%m;其实快速幂取模也是用到这个
    #include <iostream>
    using namespace std;
    
    const int mod=10007;
    
    int pow(int a,int n){
       int ans=1,base=a%mod;
       while(n){
           if(n%2==1) ans=(ans*base)%mod;
           base=(base*base)%mod;
           n=n/2;
       }
       return ans;
    }
    
    int main(){
        cout<<pow(2,110)<<endl;
        return 0;
    }

    二、快速幂

    博客对应课程的视频位置:1、快速幂
    https://www.fanrenyi.com/video/30/280

    1、朴素求法

     1 /*
     2 最朴素的求幂方法
     3 也就是平常使用pow函数,最简单的实现就是一直累乘
     4 
     5 比如求a^n
     6 
     7 */
     8 #include <iostream>
     9 using namespace std;
    10 
    11 int pow(int a,int n){
    12    int ans=1;
    13    for(int i=1;i<=n;i++){
    14        ans*=a;
    15    } 
    16    return ans;
    17 }
    18 
    19 int main(){
    20     cout<<pow(2,22)<<endl;
    21     return 0;
    22 }
    23 
    24 /*
    25 
    26 可以看到,算法的时间复杂度是O(n)。为了降低时间复杂度,
    27 我们可以使用快速幂算法,
    28 将时间复杂度降低到O(logn)。
    29 
    30 */

    2、快速幂

     1 /*
     2 
     3 快速幂:
     4 
     5 首先,快速幂的目的就是做到快速求幂,
     6 
     7 假设我们要求a^n,那么其实n是可以拆成二进制的,
     8 例如当n==11时
     9 11的二进制是1011,
    10 11 =2º×1+2¹×1+2²×0+2³×1=1+2+8,
    11 所以
    12 a^11=a^1*a^2*a^8
    13 原来算11次,现在只需要算三次
    14 
    15 具体怎么算呢:
    16 我们可以用一个变量base来在每次循环的时候记录a^i,
    17 最开始base是a
    18 然后每次循环让base=base*base
    19 那么base的值
    20 a-->a^2-->a^4-->a^8-->a^16-->a^32.......
    21 然后根据11的二进制,1011,
    22 取位为1时候的base值即可,
    23 也就是取a,a^2,a^8
    24 
    25 由此可以得到代码:
    26 
    27 
    28 */
    29 
    30 #include <iostream>
    31 using namespace std;
    32 
    33 int pow(int a,int n){
    34    int ans=1,base=a;
    35    while(n){
    36        if(n%2==1) ans=ans*base;
    37        base=base*base;
    38        n=n/2;
    39    }
    40    return ans;
    41 }
    42 
    43 int main(){
    44     cout<<pow(2,22)<<endl;
    45     return 0;
    46 }
    47 
    48 
    49 
    50 /*
    51 
    52 n 11
    53 ans a
    54 base a^2
    55 
    56 n 5
    57 ans a*a^2
    58 base a^2*a^2=a^4
    59 
    60 n 2
    61 ans a*a^2
    62 base a^4*a^4=a^8
    63 
    64 n 1
    65 ans a*a^2*a^8
    66 base a^8*a^8=a^16
    67 
    68 n 0
    69 
    70 */

    3、快速幂求模

     1 /*
     2 因为求幂运算得到的结果一般很大
     3 所以一般需要对求幂的结果进行取模
     4 所以下面就来说说快速幂取模的操作
     5 
     6 根据同余定理,我们知道
     7 (a*b)%m = ((a%m)*(b%m))%m;
     8 其实快速幂取模也是用到这个
     9 
    10 
    11 */
    12 
    13 #include <iostream>
    14 using namespace std;
    15 
    16 const int mod=10007;
    17 
    18 int pow(int a,int n){
    19    int ans=1,base=a%mod;
    20    while(n){
    21        if(n%2==1) ans=(ans*base)%mod;
    22        base=(base*base)%mod;
    23        n=n/2;
    24    }
    25    return ans;
    26 }
    27 
    28 int main(){
    29     cout<<pow(2,110)<<endl;
    30     return 0;
    31 }
     
  • 相关阅读:
    IOS中的国际化的使用(Xcode 6.0之后的使用步骤)
    KVC,KVO的区别和使用
    通知,代理,block 单例的使用和区别
    NSoperation的使用
    多线程之Nsthread的使用方法
    多线程的之GCD的介绍
    IOS中生成证书、真机调试、上线发布程序的步骤
    IOS之NavigationController跳转到指点的界面
    IOS之截取字符串的使用方法
    ios 之定时器的使用的技巧(结合runloop)使用
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/13064188.html
Copyright © 2020-2023  润新知