矩阵乘法

首先推荐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 }

 

你可能感兴趣的:(矩阵)