Description

windy在有向图中迷路了。 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1。 现在给出该有向图,你能告诉windy总共有多少种不同的路径吗? 注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间。
Input

第一行包含两个整数,N T。 接下来有 N 行,每行一个长度为 N 的字符串。 第i行第j列为’0’表示从节点i到节点j没有边。 为’1’到’9’表示从节点i到节点j需要耗费的时间。
Output

包含一个整数,可能的路径数,这个数可能很大,只需输出这个数除以2009的余数。
Sample Input
【输入样例一】

2 2

11

00

【输入样例二】

5 30

12045

07105

47805

12024

12345

Sample Output
【输出样例一】

1

【样例解释一】

0->0->1

【输出样例二】

852

HINT

30%的数据,满足 2 <= N <= 5 ; 1 <= T <= 30 。 100%的数据,满足 2 <= N <= 10 ; 1 <= T <= 1000000000 。

解法:自己见得少,拿到这题思考了,没有什么思路。看了世界爷的博客,恍然大悟。

考虑当所有边权都是1的时候 那么显然邻接矩阵自乘T次之后a[1][n]就是答案

因为当边权为1的时候a[i][j]可以表示从第i个点转移到第j个点的方案数 显然这个符合矩乘的定义

现在边权最大为9 那么将一个点拆成9个 第i个点拆成的第j+1个点向第j个点连一条边权为1的边

那么i->j有一条边权为k的边等价于i向j拆成的第k个点连边

建好这个矩阵之后,跑一个矩阵幂就行了。

//BZOJ 1297

#include <bits/stdc++.h>
using namespace std;

const int maxn = 100;
const int mod = 2009;
int n, m, t;
int getid(int i, int j){
    return (j-1)*m+i;
}

typedef struct node{
    int a[maxn][maxn];
}Matrix;

Matrix operator * (Matrix x, Matrix y){
    Matrix ans;
    for(int i=0; i<maxn; i++){
        for(int j=0; j<maxn; j++){
            ans.a[i][j]=0;
        }
    }
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            for(int k=1; k<=n; k++){
                ans.a[i][j] = (ans.a[i][j] + x.a[i][k]*y.a[k][j])%mod;
            }
        }
    }
    return ans;
}

Matrix pow(Matrix a, int n){
    Matrix res;
    for(int i=0; i<maxn; i++){
        for(int j=0; j<maxn; j++){
            if(i==j) res.a[i][j]=1;
            else res.a[i][j]=0;
        }
    }
    while(n){
        if(n&1) res = res*a;
        a = a*a;
        n>>=1;
    }
    return res;
}

int main()
{
    scanf("%d%d", &m,&t);
    n=9*m;
    Matrix aa;
    for(int i=0; i<maxn; i++){
        for(int j=0; j<maxn; j++){
            aa.a[i][j]=0;
        }
    }
    for(int i=1; i<=m; i++){
        for(int j=2; j<=9; j++){
            aa.a[getid(i,j)][getid(i,j-1)]=1;
        }
    }
    for(int i=1; i<=m; i++){
        for(int j=1; j<=m; j++){
            int x;
            scanf("%1d",&x);
            if(x==0) continue;
            aa.a[i][getid(j,x)]=1;
        }
    }
    Matrix ans = pow(aa, t);
    printf("%d\n", ans.a[1][m]);
    return 0;
}