矩阵乘法

首先推荐matrix67的一篇好文章,《十个利用矩阵乘法解决的经典题目》。讲的非常清晰。

 为什么他讲矩阵讲的很清晰呢?因为他叫matrix67。。(大雾


 矩阵乘法:Pi,j=ΣAi,k*Bk,j

显而易见 ,矩阵乘法满足结合律但不满足交换律,程序里不要写反了。


 矩阵快速幂:因为矩阵乘法满足结合律,所以可以用快速幂加速。复杂度O(n3logK)。

注意通常把矩阵的快速幂写成迭代而不是递归,因为矩阵通常比较占地方,写成迭代比较好。

1 Quickmatrix(martix m,int k){
2     //注意ans的初始化,或者在第一次使用ans时令ans=m;
3     while (k){
4         if (k&1)    ans*=m;
5         m=m*m;
6         k>>=1;
7     }
8 }

 


 常见应用1:

利用矩阵乘法加速线性递推。因为矩阵本就是描述线性变换的,所以用来表示线性递推就很自然。

例如计算斐波那契数列的第n项,就可以根据斐波那契数列的定义构造一个矩阵,使其能将向量(Fn-2,Fn-1)变换到向量(Fn-1,Fn-2+Fn-1

显然,我们可以得到,那么第n项就是这个2 x 2的矩阵自乘n次,再乘以(0,1)的结果。


 常见应用2:

利用矩阵乘法统计图中的路径方案数。

根据定义,某个图的邻接01矩阵自乘n次后,Ai,j就是从i到j经过n条边的路径方案数。

这个问题可以理解为一般意义上的计数问题。很多统计方案的问题,实质上就是其状态图中的路径方案数问题。

例如文章中的例题9


【例题】SCOI2009 迷路

给出一个有向有权图,问从1到n,长度为T的路径一共有多少条。

注意到题目中每条路径的长度不超过10,那么就可以拆点转化为应用2.

 附上代码:

View Code
  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <cstring>
  6 #include <cmath>
  7 #include <stack>
  8 #include <ctime>
  9 #define INF (9999999)
 10 #define MAXN (100+10)
 11 #define BreakTest //cout<<"Here!"<<endl;
 12 using namespace std;
 13 /*Gloable*/
 14 int map[MAXN][MAXN];
 15 int newpoint[MAXN][11],np=1;
 16 int inside[MAXN];
 17 /*ADT & reload*/
 18 struct matrix{
 19     int p[MAXN][MAXN];
 20     int x,y;
 21     matrix(){memset(p,0,sizeof(p));}
 22 }m;
 23 typedef struct matrix matrix;
 24 matrix operator * (matrix a ,matrix b){//a.x==b.y
 25     matrix ans;
 26     for(int i=1;i<=a.x;i++)
 27         for (int j=1;j<=b.y;j++)
 28             for (int k=1;k<=a.y;k++)
 29                 ans.p[i][j]=(((a.p[i][k]%2009)*(b.p[k][j]%2009))%2009+ans.p[i][j]%2009)%2009;
 30     ans.x=a.x;
 31     ans.y=b.y;
 32     return ans;
 33 }
 34 /*Funciton*/
 35 matrix quickmatrix(matrix m,long long k){
 36     matrix ans;
 37     bool exits=false;
 38     while (k){
 39         if (k&1==1){
 40             if (!exits) {ans=m;exits=true;}
 41             else
 42             ans=ans*m;
 43         }
 44         k>>=1;
 45         m=m*m;
 46     }
 47     return ans;
 48 }
 49 int main()
 50 {
 51     int n;
 52     long long t;
 53     char str[15];
 54     int i,j,k;
 55     scanf("%d%lld",&n,&t);
 56     for (i=1;i<=n;i++){
 57         scanf("%s",str);
 58         for (j=0;str[j];j++){
 59             if (str[j]!='0')
 60                 map[i][j+1]=str[j]-'0';
 61             else
 62                 map[i][j+1]=-1;
 63         }
 64     }
 65     #ifdef DEBUG
 66     for (i=1;i<=n;i++){
 67         for(j=1;j<=n;j++)
 68             cout<<map[i][j]<<"  ";
 69         cout<<endl;
 70     }
 71     #endif // DEBUG
 72 
 73 
 74 
 75     for (i=1;i<=n;i++){
 76         int maxlen=-INF;
 77         for (j=1;j<=n;j++){
 78             if (map[j][i]>maxlen)   maxlen=map[j][i];
 79         }
 80 
 81         inside[i]=maxlen-1;
 82         for (j=0;j<=inside[i];j++){
 83             newpoint[i][j]=np++;
 84         }
 85     }
 86 
 87     #ifdef DEBUG
 88     for (i=1;i<=n;i++)
 89         cout<<inside[i]<<" ";
 90     cout<<endl;
 91     #endif // DEBUG
 92 
 93 
 94 
 95     for (i=1;i<=n;i++){
 96         for (j=1;j<=inside[i];j++){
 97             m.p[newpoint[i][j]][newpoint[i][j-1]]=1;
 98         }
 99     }
100     for (i=1;i<=n;i++){
101         for (j=1;j<=n;j++){
102             if (map[i][j]!=-1){
103                 m.p[newpoint[i][0]][newpoint[j][map[i][j]-1]]=1;
104             }
105         }
106     }
107 
108     #ifdef DEBUG
109     cout<<np<<endl;
110 
111     for (i=1;i<np;i++){
112         for(j=1;j<np;j++)
113             cout<<m.p[i][j]<<" ";
114         cout<<endl;
115     }
116     #endif // DEBUG
117 
118 
119 
120     m.x=m.y=np-1;
121     matrix ans=quickmatrix(m,t);
122     printf("%d\n",ans.p[newpoint[1][0]][newpoint[n][0]]);
123     return 0;
124 
125 }

 

posted @ 2013-03-24 14:36  wsc500  阅读(563)  评论(2编辑  收藏  举报