zoukankan      html  css  js  c++  java
  • 快速幂的理解及使用

    快速幂

    1.快速幂定义

    wiki

    快速幂也称为平方求幂(exponentiating by squaring)

    快速幂时计算一个数的大正整数乘幂的一般方法(对多项式,矩阵也适用)

    \[x^n = \begin{cases} x(x^2)^{\frac{n-1}{2}}, & \text {if $n$ is odd}\\ (x^2)^{\frac{n}{2}}, & \text {if $n$ is even} \end{cases} \]

    平方法转换思想

    将指数的位,二进制的位,来确定计算哪些幂

    \[x = a * b ^n , x= a * (b^2)^{\frac{n}{2}} \]

    每次把b进行平方,将n看作一个二进制的数,如果k位为1,则最后的结果需要乘上 b(2k)

    b= 13(1101)

    \[x = b^{13} , = b^1 * b^{4} * b^8 \]

    代码实现

    # a * b^n
    def quickPower(a,b,n):
      x = a
      p = b
      while n >0:
        if(n & 1) == 1:
          x = x * p
        p = p * p   # p,p^2,p^4,p^8
        n = n >> 1
      return x
    	
    
    • 上述对矩阵同样适用
    • 由于幂函数求解,数值会比较大,通常在每一步计算的时候都会进行取余操作
    // b^n
    int MOD = 10e9;
    long long power(long long p,long long n){
      long long ans = 1;
      while(n > 0){
        if (n & 1 == 1) ans = (ans * p) % MOD;
        p = p * p % MOD;
        n >>=1;
      }
    }
    

    2.快速幂应用

    计算大指数幂除以一个数的余数,在密码学中应用较多

    LeetCode.372超级次方

    // a^b % MOD
    // b是以一个大数,保存在数组中
    class Solution {
        private int MOD = 1337;
        public int superPow(int a, int[] b) {
          	return dfs(a,b,b.length -1);
        }
        private int dfs(int a,int[] b,int len){
            if(len == -1) return 1;
            return quickPow(dfs(a,b,len-1),10)  * quickPow(a,b[len]) % MOD;
        }
      	private int quickPow(int a ,int b){
        		int ans = 1;
            a %= MOD;
            while(b > 0){
                if( b & 1) ans = ans * a % MOD;
                a = a * a % MOD;
                b = b >> 1;
            }
            return ans;
        }
    }
    

    快速幂在动态规划中的应用

    动态规划主要用来解决两种问题:

    • 1.优化问题
    • 2.组合计数问题

    快速幂可以在组合计数问题中,对计算进行加速(时间复杂度从 O(n) -> O(logn))

    [LeetCode.1411]

    \[dp[i][0] = dp[i-1][0] * 3 + dp[i-1][1] * 2 , dp[i][1] = dp[i-1][0] * 2 + dp[i-1][1] * 2 \]

    边界条件

    \[dp[1][0] = dp[1][0] = 6 \]

        int numOfWays(int n) {
            constexpr int MOD = 1e9 + 7;
            
            vector<vector<long>> dp(n+1,vector<long>(2,6));
            for(int i = 2;i<=n;i++){
                dp[i][0] = (dp[i-1][0] * 3 + dp[i-1][1] *2) % MOD;
                dp[i][1] = (dp[i-1][0] * 2 + dp[i-1][1] *2) % MOD;
            }
            return (dp[n][0] + dp[n][1]) % MOD;
        }
    

    转换为矩阵求解

    \[(dp[i][0],dp[i][1]) = (dp[i-1][0] ,dp[i-1][1]) * \begin{matrix} 3&2\\ 2&2\\ \end{matrix} , (dp[n][0], dp[n][1] = (dp[1][0] , dp[1][1])* \begin{matrix} 3&2\\ 2&2\\ \end{matrix} ^{n-1} \]

    class Solution {
    public:
      int numOfWays(int n) {
        constexpr long kMod = 1e9 + 7;
        vector<vector<long>> ans{{6, 6}}; // 1x2
        vector<vector<long>> M{{3, 2},{2,2}}; // 2x2
        auto mul = [kMod](const vector<vector<long>>& A, 
                          const vector<vector<long>>& B) {
          const int m = A.size(); // m * n
          const int n = B.size(); // n * p
          const int p = B[0].size();
          vector<vector<long>> C(m, vector<long>(p));
          for (int i = 0; i < m; ++i)
            for (int j = 0; j < p; ++j)
              for (int k = 0; k < n; ++k)
                C[i][j] += (A[i][k] * B[k][j]) % kMod;
          return C;
        };
        --n;
        while (n) {      
          if (n & 1) ans = mul(ans, M); // ans = ans * M;
          M = mul(M, M); // M = M^2
          n >>= 1;
        }
        // ans = ans0 * M^(n-1)
        return (ans[0][0] + ans[0][1]) % kMod;
      }
    };
    
    不要用狭隘的眼光看待不了解的事物,自己没有涉及到的领域不要急于否定. 每天学习一点,努力过好平凡的生活.
  • 相关阅读:
    eclipse中svn的各种状态图标详解
    Invalid configuation file. File "**********" was created by a VMware product with more feature than this version of VMware Workstation and cannot be
    linux下tomcat无法访问问题(换一种说法:无法访问8080端口)
    安装MySQL start Service(无法启动服务)
    eclipse下SVN subclipse插件
    tomcat启动窗口中的时间与系统时间不一致
    关于如果从SQLSERVER中获取 数据库信息 或者 表信息
    有关google的appengine部署服务器的简单教程
    部署到Google App Engine时中途退出后引起的问题
    重温WCF之数据契约中使用枚举(转载)(十一)
  • 原文地址:https://www.cnblogs.com/GeekDanny/p/15779513.html
Copyright © 2011-2022 走看看