zoukankan      html  css  js  c++  java
  • poj3233 题解 矩阵乘法 矩阵快速幂

    题意:求S = A + A2 + A3 + … + Ak.(mod m)

    这道题很明显可以用矩阵乘法,但是这道题的矩阵是分块矩阵,

      分块矩阵概念如下:当一个矩阵A中的单位元素aij不是一个数值而是一个矩阵是A矩阵称为分块矩阵,在性质满足的前提下依然满足矩阵加法乘法。 例如矩阵乘法A×B,将B按行分块,可以看成矩阵A乘列向量,其中B中每个元素是一个行向量;将A按列分块同理。

      简单地说,就是矩阵里的元素还是个矩阵。这道题我们可以像这样构建矩阵:

            ∵Sn=Sn-1+Ak   有如下转移图

               

            写出邻接矩阵 (下图用E表示单位矩阵 也就是"1”,0表示全是0的矩阵 也就是“0”,A即为输入的矩阵)

            

            也就有:

                    

            最终答案是:                                 

              

    所以,最终C++程序只需要重载运算符就可以轻松AC了

    而另一种做法,也就是二分加矩阵快速幂则需要较长时间(800+MS)

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <cmath>
      4 #include <ctime>
      5 #include <cstring>
      6 #include <cstdio>
      7 #include <cstdlib>
      8 
      9 using namespace std;
     10 
     11 int    n,k,m;
     12 
     13 class Matrix
     14 {
     15     public:
     16     int    val[31][31];
     17     int    x,y;
     18 
     19     Matrix()
     20     {
     21         memset(val,0,sizeof(val));
     22         x=y=0;
     23         return ;
     24     }
     25     
     26     void    set_E()
     27     {
     28         int    i;
     29         for(i=1;i<=x;++i)
     30             val[i][i]=1;
     31         return ;
     32     }
     33     
     34     Matrix operator*(Matrix b)
     35     {
     36         int    i,j,k;
     37         Matrix    c;
     38         c.resize(x,b.y);
     39     
     40         for(k=1;k<=b.x;++k)
     41         for(i=1;i<=x;++i)
     42         if(val[i][k])//不加这行就要340+MS
     43         for(j=1;j<=b.y;++j)
     44             c.val[i][j]=(c.val[i][j]+val[i][k]*b.val[k][j])%m;
     45         return c;
     46     }
     47 
     48     Matrix    operator+(Matrix b)
     49     {
     50         Matrix    c;
     51         c.resize(max(x,b.x),max(y,b.y));
     52         int    i,j;
     53         
     54         for(i=1;i<=c.x;++i)
     55         for(j=1;j<=c.y;++j)
     56             c.val[i][j]=(val[i][j]+b.val[i][j])%m;
     57         
     58         return c;
     59     }
     60 
     61     void    resize(const int & _x,const int & _y)
     62     {
     63         x=_x,y=_y;
     64         return ;
     65     }
     66 }A;
     67 
     68 class    Matrix_Plus
     69 {
     70     public:
     71     Matrix    val[3][3];
     72     int    x,y;
     73     
     74     Matrix_Plus()
     75     {
     76         memset(val,0,sizeof(val));
     77         x=y=0;
     78         return ;
     79     }
     80 
     81     void    set_E()
     82     {
     83         int    i;
     84         for(i=1;i<=x;++i)
     85             val[i][i].set_E();
     86         return ;
     87     }
     88 
     89 
     90     Matrix_Plus operator*(Matrix_Plus b)
     91     {
     92         Matrix_Plus    c;
     93         int    i,j,k;
     94         c.resize(x,b.y);
     95         
     96         for(k=1;k<=b.x;++k)
     97         for(i=1;i<=x;++i)
     98         for(j=1;j<=b.y;++j)
     99             c.val[i][j]=c.val[i][j]+val[i][k]*b.val[k][j];
    100         return c;
    101     }
    102     
    103     Matrix_Plus operator^(int    p)
    104     {
    105         Matrix_Plus    r,base;
    106         r.resize(2,2);
    107         r.val[1][1].resize(n,n);
    108         r.val[1][2].resize(n,n);
    109         r.val[2][1].resize(n,n);
    110         r.val[2][2].resize(n,n);
    111         r.set_E();
    112         base=*this;
    113         
    114         while(p)
    115         {
    116             if(p&1)
    117                 r=r*base;
    118             base=base*base;
    119             p>>=1;
    120         }
    121         
    122         return r;
    123     }
    124     
    125     void    resize(const int & _x,const int & _y)
    126     {
    127         x=_x,y=_y;
    128         return ;
    129     }
    130 
    131 }S,A_;
    132         
    133 int main()
    134 {    
    135     int    i,j;
    136     
    137     scanf("%d%d%d",&n,&k,&m);
    138     A.resize(n,n);
    139     
    140     for(i=1;i<=n;++i)
    141     {
    142         for(j=1;j<=n;++j)
    143         {
    144             scanf("%d",&A.val[i][j]);
    145         }
    146     }
    147     
    148     S.resize(1,2);
    149     S.val[1][2]=A;
    150     S.val[1][1].resize(n,n);
    151     S.val[1][2].resize(n,n);
    152     
    153     A_.resize(2,2);
    154     A_.val[1][1].resize(n,n);
    155     A_.val[1][2].resize(n,n);
    156     A_.val[2][1].resize(n,n);
    157     A_.val[2][2].resize(n,n);
    158     A_.val[1][1].set_E();
    159     A_.val[2][1].set_E();
    160     A_.val[2][2]=A;    
    161     S=S*(A_^k);
    162     
    163     for(i=1;i<=n;++i)
    164     {
    165         for(j=1;j<=n;++j)
    166             printf("%d ",S.val[1][1].val[i][j]);
    167         printf("
    ");
    168     }
    169     return 0;
    170 }
  • 相关阅读:
    清除缓存
    框架更新 (简)
    Xutils简
    动画
    夜间模式
    TabLoaout简单框架
    atomic原子类的理解
    单例模式中指令重排序及需要使用volatile的理解
    对volatile的理解
    jvm内存模型及垃圾回收GC
  • 原文地址:https://www.cnblogs.com/Gster/p/4703087.html
Copyright © 2011-2022 走看看