• POJ 3233 矩阵乘法


    题意:求解A+A^2+...+A^k

    题解:

    1)利用通和公式,原式=(A^k+1 - A)(A - O)^-1 时间复杂度O(n^3lgk)

    2)递归求解,A+A^2+...+A^k=(A+A^2+...+A^k/2)+A^k/2(A+A^2+...+A^k/2) 时间复杂度O(n^3lgk^2)

    逆矩阵貌似繁琐,直接用第二种方法写的

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    #include <utility>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)>(y)?(y):(x))
    
    using namespace std;
    
    int n,MOD,k;
    
    struct Matrix{
        int n,m;
        vector< vector<int> >a;
        Matrix(){};
        Matrix(const Matrix & T) : n(T.n),m(T.m)
        {
            a.resize(n);
            for(int i=0; i<n; i++)
            {
                a[i].resize(m);
                for(int j=0; j<m; j++)
                    a[i][j]=T.a[i][j];
            }
        }
        Matrix(int N, int M)
        {
            n=N;
            m=M;
            a.resize(N);
            for(int i=0; i<N; i++)
                a[i].resize(M);
        }
        Matrix & operator=(const Matrix &T)
        {
            n=T.n;
            m=T.m;
            a.resize(n);
            for(int i=0; i<n; i++)
            {
                a[i].resize(m);
                for(int j=0; j<m; j++)
                    a[i][j]=T.a[i][j];
            }
            return *this;
        }
        Matrix operator+(const Matrix &T) const
        {
            Matrix tmp(n,m);
            for(int i=0; i<n; i++)
                for(int j=0; j<m; j++)
                tmp.a[i][j]=(a[i][j]+T.a[i][j])%MOD;
            return tmp;
        }
        Matrix operator*(const Matrix &T) const
        {
            Matrix tmp(n,T.m);
            for(int i=0; i<n; i++)
                for(int j=0; j<T.m; j++)
                    for(int k=0; k<m; k++)
                    tmp.a[i][j]=(tmp.a[i][j]+a[i][k]*T.a[k][j])%MOD;
            return tmp;
        }
        void input(int N, int M)
        {
            n=N;
            m=M;
            a.resize(n);
            for(int i=0; i<n; i++)
            {
                a[i].resize(m);
                for(int j=0; j<m; j++)
                scanf("%d",&a[i][j]);
            }
        }
        void output()
        {
            for(int i=0; i<n; i++)
            {
                for(int j=0; j<m; j++)
                    printf("%d ",a[i][j]);
                printf("
    ");
            }
        }
        Matrix pow_m(int N)//矩阵满足n=m 矩阵快速幂
        {
            Matrix ret(n,n),tmp(*this);
            for(int i=0; i<n; i++)
                ret.a[i][i]=1;
            while(N)
            {
                if(N&1) ret=ret*tmp;
                tmp=tmp*tmp;
                N>>=1;
            }
            return ret;
        }
    }ans,A;
    
    void work(int k)
    {
        if(k==1)
        {
            ans=A;
            return;
        }
        if(k==0)
        {
            ans=A.pow_m(0);
            return;
        }
        work(k/2);
        ans=ans*(A.pow_m(0)+A.pow_m(k/2));
        if(k&1) ans=ans+A.pow_m(k);
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&k,&MOD);
        A.input(n,n);
        work(k);
        ans.output();
        return 0;
    }
    View Code

    太刁了

    看到这种解法。

    |A O|^k+1 =|A^k+1    O|

    |E E|    |A^k+...+A^0 E|

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    #include <utility>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)>(y)?(y):(x))
    
    using namespace std;
    
    int n,MOD,k;
    
    struct Matrix{
        int n,m;
        vector< vector<int> >a;
        Matrix(){};
        Matrix(const Matrix & T) : n(T.n),m(T.m)
        {
            a.resize(n);
            for(int i=0; i<n; i++)
            {
                a[i].resize(m);
                for(int j=0; j<m; j++)
                    a[i][j]=T.a[i][j];
            }
        }
        Matrix(int N, int M)
        {
            n=N;
            m=M;
            a.resize(N);
            for(int i=0; i<N; i++)
                a[i].resize(M);
        }
        Matrix & operator=(const Matrix &T)
        {
            n=T.n;
            m=T.m;
            a.resize(n);
            for(int i=0; i<n; i++)
            {
                a[i].resize(m);
                for(int j=0; j<m; j++)
                    a[i][j]=T.a[i][j];
            }
            return *this;
        }
        Matrix operator+(const Matrix &T) const
        {
            Matrix tmp(n,m);
            for(int i=0; i<n; i++)
                for(int j=0; j<m; j++)
                tmp.a[i][j]=(a[i][j]+T.a[i][j])%MOD;
            return tmp;
        }
        Matrix operator*(const Matrix &T) const
        {
            Matrix tmp(n,T.m);
            for(int i=0; i<n; i++)
                for(int j=0; j<T.m; j++)
                    for(int k=0; k<m; k++)
                    tmp.a[i][j]=(tmp.a[i][j]+a[i][k]*T.a[k][j])%MOD;
            return tmp;
        }
        void input(int N, int M)
        {
            n=N;
            m=M;
            a.resize(n);
            for(int i=0; i<n; i++)
            {
                a[i].resize(m);
                for(int j=0; j<m; j++)
                scanf("%d",&a[i][j]);
            }
        }
        void output()
        {
            for(int i=0; i<n; i++)
                for(int j=0; j<m; j++)
                    if(j<m-1) 
                        printf("%d ",a[i][j]);
                    else
                        printf("%d
    ",a[i][j]);
        }
        Matrix pow_m(int N)//矩阵满足n=m 矩阵快速幂
        {
            Matrix ret(n,n),tmp(*this);
            for(int i=0; i<n; i++)
                ret.a[i][i]=1;
            while(N)
            {
                if(N&1) ret=ret*tmp;
                tmp=tmp*tmp;
                N>>=1;
            }
            return ret;
        }
    };
    
    int main()
    {
        scanf("%d%d%d",&n,&k,&MOD);
        Matrix A(2*n,2*n);
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
            scanf("%d",&A.a[i][j]);
    
        for(int i=0; i<2*n; i++)
            A.a[n+i%n][i]=1;
        A=A.pow_m(k+1);
    
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
            {
                if(i==j) A.a[n+i][j]=(A.a[n+i][j]+MOD-1)%MOD;
                if(j<n-1)
                    printf("%d ",A.a[n+i][j]);
                else
                    printf("%d
    ",A.a[n+i][j]);
            }
        return 0;
    }
    View Code
  • 相关阅读:
    1856: [Scoi2010]字符串(Catalan数)
    11.6NOIP模拟赛
    bzoj1257[CQOI2007]余数之和(除法分块)
    11.5NOIP模拟赛
    bzoj1048(记忆化搜索)
    置顶公告+更新日志
    CF585F Digits of Number Pi
    [SHOI2007]善意的投票
    [HEOI2015]最短不公共子串
    树形背包复杂度+P3177 [HAOI2015]树上染色
  • 原文地址:https://www.cnblogs.com/Mathics/p/3954044.html
Copyright © 2020-2023  润新知