zoukankan      html  css  js  c++  java
  • POJ3233不错的矩阵(矩阵套矩阵)

    题意:
           给一个n*n的矩阵A,然后求S=A + A^2 + A^3 + ..+ A^k.


    思路:
          矩阵快速幂,这个题目挺新颖的,以往的矩阵快速幂都是退出公式,然后构造矩阵,这个比较特别,直接上子矩阵吧
    A 1   平方后得到 A^2 1+A  三次方   A^3   1+A+A^2
    0 1               0   1             0     1       ...这样就行了,
    还有注意这个是矩阵套矩阵,然后就是快速幂了,比较容易实现,有一点要注意,

    大矩阵的单位矩阵只有对角线才是单位小矩阵,还有一个地方,就是最后我们要在大矩阵的1 2 位置减去单位矩阵,这个减去单位矩阵后如果比0小怎么办,我的处理方法是比0小就再加上余数。


    #include<stdio.h>
    #include<string.h>
    
    typedef struct
    {
        int mat[32][32];
    }M;
    
    typedef struct
    {
        M MAT[3][3];
    }MM;
    
    int n ,MOD;
    
    M matM(M a ,M b)
    {
        M c;
        memset(c.mat ,0 ,sizeof(c.mat));
    
        for(int k = 1 ;k <= n ;k ++)
        for(int i = 1 ;i <= n ;i ++)
        if(a.mat[i][k])
        for(int j = 1 ;j <= n ;j ++)
        c.mat[i][j] = (c.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % MOD;
        return c;
    }
    
    M addM(M a ,M b)
    {
        M c;
        memset(c.mat ,0 ,sizeof(c.mat));
        for(int i = 1 ;i <= n ;i ++)
        for(int j = 1 ;j <= n ;j ++)
        c.mat[i][j] = (a.mat[i][j] + b.mat[i][j]) % MOD;
        return c;
    }
    
    MM matMM(MM a ,MM b)
    {
        MM c;
        for(int i = 1 ;i <= 2 ;i ++)
        for(int j = 1 ;j <= 2 ;j ++)
        for(int k = 1 ;k <= n ;k ++)
        for(int l = 1 ;l <= n ;l ++)
        c.MAT[i][j].mat[k][l] = 0;
    
        for(int i = 1 ;i <= 2 ;i ++)
        for(int j = 1 ;j <= 2 ;j ++)
        for(int k = 1 ;k <= 2 ;k ++)
        c.MAT[i][j] = addM(c.MAT[i][j] ,matM(a.MAT[i][k] ,b.MAT[k][j]));
    
        return c;
    }
    
    MM quickMM(MM a ,int b)
    {
        MM c;
        for(int i = 1 ;i <= 2 ;i ++)
        for(int j = 1 ;j <= 2 ;j ++)
        for(int k = 1 ;k <= n ;k ++)
        for(int l = 1 ;l <= n ;l ++)
        c.MAT[i][j].mat[k][l] = 0;
    
        for(int k = 1 ;k <= n ;k ++)
        c.MAT[1][1].mat[k][k] = c.MAT[2][2].mat[k][k] = 1;
    
        while(b)
        {
            if(b & 1) c = matMM(c ,a);
            a = matMM(a ,a);
            b >>= 1;
        }
        return c;
    }
    
    int main ()
    {
        int i ,j ,b;
        MM A;
        while(~scanf("%d %d %d" ,&n ,&b ,&MOD))
        {
            //MOD = 10000000;
            for(i = 1 ;i <= n ;i ++)
            for(j = 1 ;j <= n ;j ++)
            {
                scanf("%d" ,&A.MAT[1][1].mat[i][j]);
                A.MAT[2][1].mat[i][j] = 0;
                if(i == j)
                A.MAT[1][2].mat[i][j] = A.MAT[2][2].mat[i][j] = 1;
                else  A.MAT[1][2].mat[i][j] = A.MAT[2][2].mat[i][j] = 0;
            }
    
            MM ans = quickMM(A ,b + 1);
    
            for(int i = 1 ;i <= n ;i ++)
            for(int j = 1 ;j <= n ;j ++)
            {
                if(i == j) ans.MAT[1][2].mat[i][j] --;
    
                if(ans.MAT[1][2].mat[i][j] < 0) ans.MAT[1][2].mat[i][j] += MOD;
    
                if(j == n) printf("%d
    ",ans.MAT[1][2].mat[i][j]);
                else printf("%d " ,ans.MAT[1][2].mat[i][j]);
            }
        }
        return 0;
    
    }
    


  • 相关阅读:
    HDU 3681 Prison Break 越狱(状压DP,变形)
    POJ 2411 Mondriaan's Dream (状压DP,骨牌覆盖,经典)
    ZOJ 3471 Most Powerful (状压DP,经典)
    POJ 2288 Islands and Bridges (状压DP,变形)
    HDU 3001 Travelling (状压DP,3进制)
    POJ 3311 Hie with the Pie (状压DP)
    POJ 1185 炮兵阵地 (状压DP,轮廓线DP)
    FZU 2204 7
    POJ 3254 Corn Fields (状压DP,轮廓线DP)
    ZOJ 3494 BCD Code (数位DP,AC自动机)
  • 原文地址:https://www.cnblogs.com/csnd/p/12062438.html
Copyright © 2011-2022 走看看