• 矩阵


    定义

    只有(A的行数)(B的列数)相等,这两个矩阵才可以相乘

    (A)是一个(n imes p)的矩阵,(B)是一个(p imes m)的矩阵。

    (A imes B=C),那么(C)肯定是一个(n imes m)的矩阵。

    矩阵(C)中的​元素可以表示为

    [C_{i,j}=sum_{k=1}^PA_{i,k}B_{k,j} ]

    举个栗子:

    [left[egin{matrix}3&3&7&8 \end{matrix} ight] imesleft[egin{matrix}4\5\8\1\8end{matrix} ight]=left[egin{matrix}12&15&24&3&24\12&15&24&3&24\28&35&56&7&56\32&40&64&8&64\end{matrix} ight] ]

    国家级冠军的必备千位数加减!

    矩阵乘法不满足交换律(不用说都知道),但是满足结合律。

    也很好证明。

    (A imes B imes C=D)

    (A imes B=T)

    [D_{i,j}=sum_{x=1}^qT_{i,x} imes C_{x,j}\D_{i,j}=sum_{x=1}^q(sum_{y=1}^pA_{i,y} imes B_{y,x}) imes C_{x,j}\D_{i,j}=sum_{x=1}^qsum_{y=1}^pA_{i,y} imes B_{y,x} imes C_{x,j} ]

    (A imes (B imes C)=E)

    同理得

    [E_{i,j}=sum_{x=1}^psum_{y=1}^qA_{i,x} imes B_{x,y} imes C_{y,j} ]

    可得(D=E)

    方阵

    一个(n imes n)的矩阵

    因为行数和列数相等,所以方阵的幂有意义。

    我们就可以利用快速幂优化方阵。

    。。。

    优化线性递推

    求斐波那契数列的第(n)项(POJ3070)

    (1le nle10^{18}),对大质数取模

    (f_0=0,f_1=1,f_n=f_{n-1}+f_{n-2})

    我们设矩阵(A_n=left[egin{matrix}f_n,f_{n-1}end{matrix} ight])

    弄一个矩阵

    [left[egin{matrix}0&1\1&1end{matrix} ight] ]

    (A_{n-1})乘上这玩意就是(A_n)

    于是我们就可以使用矩阵乘法快速幂。

    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    typedef long long ll;
    const int SZ = 2;
    const ll P = 10000;
    
    struct Mat
    {
        ll a[SZ + 5][SZ + 5];
    } ys, ans;
    
    inline Mat mul(Mat a, Mat b)
    {
        Mat res;
        ll r;
        memset(res.a, 0, sizeof(res.a));
        for (int i = 1; i <= SZ; i++)
            for (int k = 1; k <= SZ; k++)
            {
                r = a.a[i][k];
                for (int j = 1; j <= SZ; j++)
                    (res.a[i][j] += b.a[k][j] * r) %= P;
            }
        return res;
    }
    
    inline void qpow(ll p)
    {
        for (; p; p >>= 1, ys = mul(ys, ys))
            if (p & 1) ans = mul(ans, ys);
    }
    
    void init()
    {
        memset(ans.a, 0, sizeof(ans.a));
        for (int i = 1; i <= SZ; i++) ans.a[i][i] = 1;
        memset(ys.a, 0, sizeof(ys.a));
        ys.a[1][2] = ys.a[2][1] = ys.a[2][2] = 1ll;
    }
    
    int main()
    {
        ll n;
        for (; scanf("%lld", &n), ~n;)
            if (n <= 1) printf("%lld
    ", n);
            else init(), qpow(n + 1), printf("%lld
    ", ans.a[1][1]);
        return 0;
    }
    

    Luogu P5110 块速递推

    给出数列(a),满足(a_0=0,a_1=1,a_n=233a_{n-1}+666a_{n-2}),求(A_n),对(10^9+7)取模

    (n<2^{64},1le Tle5 imes10^7)

    (T)组询问,每个询问查询(A_n),求所有询问答案的异或和

    设矩阵(left[egin{matrix}A_{n-1}&A_nend{matrix} ight])

    老套路

    [left[egin{matrix}A_{n-1}&A_nend{matrix} ight]\=left[egin{matrix}A_{n-2}&A_{n-1}end{matrix} ight] imesleft[egin{matrix}0&666\1&233end{matrix} ight] ]

    但是询问数大的一批。

    我们可以预处理出到(sqrt n)的答案,询问时只要将(n)拆为一个(ak+b)的数,直接(O(1))查询。

    #pragma GCC optimize("inline,Ofast", 3)
    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #pragma GCC optimize("-fgcse")
    #pragma GCC optimize("-fgcse-lm")
    #pragma GCC optimize("-fipa-sra")
    #pragma GCC optimize("-ftree-pre")
    #pragma GCC optimize("-ftree-vrp")
    #pragma GCC optimize("-fpeephole2")
    #pragma GCC optimize("-ffast-math")
    #pragma GCC optimize("-fsched-spec")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC optimize("-falign-jumps")
    #pragma GCC optimize("-falign-loops")
    #pragma GCC optimize("-falign-labels")
    #pragma GCC optimize("-fdevirtualize")
    #pragma GCC optimize("-fcaller-saves")
    #pragma GCC optimize("-fcrossjumping")
    #pragma GCC optimize("-fthread-jumps")
    #pragma GCC optimize("-funroll-loops")
    #pragma GCC optimize("-fwhole-program")
    #pragma GCC optimize("-freorder-blocks")
    #pragma GCC optimize("-fschedule-insns")
    #pragma GCC optimize("inline-functions")
    #pragma GCC optimize("-fschedule-insns2")
    #pragma GCC optimize("-fstrict-aliasing")
    #pragma GCC optimize("-fstrict-overflow")
    #pragma GCC optimize("-falign-functions")
    #pragma GCC optimize("-fcse-skip-blocks")
    #pragma GCC optimize("-fcse-follow-jumps")
    #pragma GCC optimize("-fsched-interblock")
    #pragma GCC optimize("-fpartial-inlining")
    #pragma GCC optimize("no-stack-protector")
    #pragma GCC optimize("-freorder-functions")
    #pragma GCC optimize("-findirect-inlining")
    #pragma GCC optimize("inline-small-functions")
    #pragma GCC optimize("-finline-small-functions")
    #pragma GCC optimize("-ftree-switch-conversion")
    #pragma GCC optimize("-foptimize-sibling-calls")
    #pragma GCC optimize("-fexpensive-optimizations")
    #pragma GCC optimize("-funsafe-loop-optimizations")
    #pragma GCC optimize("inline-functions-called-once")
    #pragma GCC optimize("-fdelete-null-pointer-checks")
    
    #include <bits/stdc++.h>
    
    using namespace std;
    typedef unsigned long long llu;
    typedef long long ll;
    const int N = 32000, P = 1e9 + 7;
    
    struct Mat
    {
        int a[2][2];
        inline Mat operator* (const Mat &t) const
        {
            Mat res;
            res.a[0][0] = (1ll * a[0][0]* t.a[0][0] + 1ll * a[0][1] * t.a[1][0]) % P;
            res.a[0][1] = (1ll * a[0][0]* t.a[0][1] + 1ll * a[0][1] * t.a[1][1]) % P;
            res.a[1][0] = (1ll * a[1][0]* t.a[0][0] + 1ll * a[1][1] * t.a[1][0]) % P;
            res.a[1][1] = (1ll * a[1][0]* t.a[0][1] + 1ll * a[1][1] * t.a[1][1]) % P;
            return res;
        }
    } m1[N + 5], m2[N + 5], s;
    llu SA, SB, SC;
    
    llu Rand()
    {
        SA ^= SA << 32, SA ^= SA >> 13, SA ^= SA << 1;
        llu t = SA;
        SA = SB, SB = SC, SC ^= t ^ SA;
        return SC;
    }
    
    int main()
    {
        s = {233, 666, 1, 0}, m1[0] = m2[0] = {1, 0, 0, 1}; 
        for (int i = 1; i <= N; i++) m1[i] = m1[i - 1] * s;
        s = m1[N];
        for (int i = 1; i <= N; i++) m2[i] = m2[i - 1] * s;
        int T;
        scanf("%d%llu%llu%llu", &T, &SA, &SB, &SC);
        int ans = 0;
        for (int n; T--;)
            n = (Rand() - 1) % (P - 1), ans ^= (m2[n / N] * m1[n % N]).a[0][0];
        return printf("%d
    ", ans), 0;
    }
    ```cpp
  • 相关阅读:
    【Python学习之旅】---模块介绍(re模块,正则表达式)
    【Python学习之旅】---模块介绍(sys模块)
    【Python学习之旅】---模块介绍(随机模块)
    【Python学习之旅】---模块介绍(时间模块)
    【Python学习之旅】---模块介绍(调用与执行)
    【Python学习之旅】---装饰器实现(高阶函数+函数嵌套+闭包,不修改函数调用方式和源代码)
    【Python学习之旅】---生成器的好处
    Educational Codeforces Round 61 (Rated for Div. 2) C
    牛客练习赛41 B. 666RPG
    牛客练习赛41 B. 666RPG
  • 原文地址:https://www.cnblogs.com/oply/p/12763594.html
Copyright © 2020-2023  润新知