zoukankan      html  css  js  c++  java
  • 矩阵优化

      前几天武理的新生赛考了道矩阵优化的斐波那契,感觉忘得差不多了

    前置知识

    • 矩阵乘法

      一个 n * p 的矩阵 A 和一个 p * m 的矩阵 B 相乘得到 n * m 的矩阵 C ,其中 C[i][j] = ∑A[i][k] * B[k][j] ; (k = 1, 2, 3... n)

    • 矩阵快速幂

      与普通快速幂相似,初始化cnt, x,再重载一下运算符,即可直接套ksm的板子

    node ksm(ll y)
    {
        node cnt, x; 
        初始化cnt, x;
        while(y)
        {
            if(y & 1) cnt = cnt * x;
            x = x * x; y >>= 1;
        }
        return cnt;
    }
    伪代码

    矩阵优化

    • 适用范围
    1.  n 非常大,通常在long long
    2.  转移决策较少,系数为常数
    3.  通常会对一个数取模

      矩阵优化能在 O(logn) 的时间内算出 f[n] 的值

    • 步骤

      以斐波那契数列为例

      1. 计算递推式

      f[n] = f[n - 1] + f[n - 2];

      2. 构造矩阵

      我们将 {f[i], f[i - 1]} 视为一个 1 * 2 的矩阵,需要乘上一个 2 * 2 的矩阵使其转化成 {f[i], f[i - 1]},即向后递推一位

      通过计算可得,这个 2 * 2 的矩阵 x 为 

      3. 矩阵快速幂

      通过矩阵进行递推,将原本只需一步的转移变成多次加乘,看起来更加复杂了。但是,矩阵的转移可以用上快速幂,n 次转移即相当于  {f[i], f[i - 1]} * x ^ n

    • 模板

      luogu1962 斐波那契数列

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    const ll mod = 1000000007;
    
    struct node
    {
        ll dp[3][3];
        void clear() {memset(dp, 0, sizeof(dp));}
    }f, ans;
    
    node operator * (node x, node y)
    {
        node cnt; cnt.clear();
        for(int i = 1; i <= 2; i++)
            for(int j = 1; j <= 2; j++)
                for(int k = 1; k <= 2; k++)
                    cnt.dp[i][j] = (cnt.dp[i][j] + x.dp[i][k] * y.dp[k][j] % mod) % mod;
        return cnt;
    }
    
    node ksm(ll y)
    {
        node cnt, x; cnt.clear(); x.clear();
        cnt.dp[1][1] = cnt.dp[1][2] = 1;
        x.dp[1][1] = x.dp[1][2] = x.dp[2][1] = 1;
        while(y)
        {
            if(y & 1) cnt = cnt * x;
            x = x * x; y >>= 1;
        }
        return cnt;
    }
    
    int main()
    {
        ll n; cin >> n;
        if(n <= 2) {cout << 1; return 0;}
        f.dp[1][1] = f.dp[1][2] = 1;
        node ans = ksm(n - 2);//{f[2], f[1]}经过n - 2次转移得到{f[n], f[n - 1]}
        cout << ans.dp[1][1];
        return 0;
    }
    luogu1962
  • 相关阅读:
    python库--pandas--DataFrame
    python库--pandas--Series
    python模块--collections(容器数据类型)
    Linux命令
    pycharm安装
    利用Anaconda进行python爬虫环境的配置-安装scrapy
    反射
    异常处理
    类的相关判断函数
    python random
  • 原文地址:https://www.cnblogs.com/XYZinc/p/11897028.html
Copyright © 2011-2022 走看看