zoukankan      html  css  js  c++  java
  • 矩阵乘法

    首先推荐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 }
    wsc500原创,转载请注明出处。请注明 出自http://www.cnblogs.com/loveidea/
  • 相关阅读:
    点分治练习
    PKU-2723 Get Luffy Out(2-SAT+二分)
    tarjan求割点与割边
    tarjan缩点练习 洛谷P3387 【模板】缩点+poj 2186 Popular Cows
    数算日子荣耀神
    《JavaScript DOM编程艺术》笔记
    CSS链接的样式a:link,a:visited,a:hover,a:active
    chrome调试技巧--持续更新
    CSS文字大小单位PX、EM的区别
    【转】如何成为一名优秀的web前端工程师(前端攻城师)?
  • 原文地址:https://www.cnblogs.com/loveidea/p/2978570.html
Copyright © 2011-2022 走看看