题目
Description
windy在有向图中迷路了。
该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1。
现在给出该有向图,你能告诉windy总共有多少种不同的路径吗?
注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间。
该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1。
现在给出该有向图,你能告诉windy总共有多少种不同的路径吗?
注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间。
Input
第一行包含两个整数,N T。
接下来有 N 行,每行一个长度为 N 的字符串。
第i行第j列为'0'表示从节点i到节点j没有边。
为'1'到'9'表示从节点i到节点j需要耗费的时间。
接下来有 N 行,每行一个长度为 N 的字符串。
第i行第j列为'0'表示从节点i到节点j没有边。
为'1'到'9'表示从节点i到节点j需要耗费的时间。
Output
输出一个整数,可能的路径数,这个数可能很大,只需输出这个数除以2009的余数。
Sample Input
2 2 11 00
Sample Output
1
Data Constraint
Hint
100%的数据,满足 2 <= N <= 10 ; 1 <= T <= 1000000000 。
分析
- 首先如果我们这个图只有0和1的话,这个矩阵的T次方就是答案
- 为什么
- 设f[k][i][j]为在k时刻走到i,j的方案数 显然 f[k][i][j]=∑1-n f[k-a[i][j]][i][j] a[i][j]不都是1吗 那么化简
- f[k][i][j]=∑1-n f[k-1][i][j] 不就和原方程一样吗
- 然后对于这道题
- 我们拆点
- 拆成多个为一的点求矩阵快速幂
代码
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int maxn=90,p=2009; 5 int tmp[maxn][maxn],bb[maxn][maxn], ans[maxn][maxn]; 6 int id,n,t; 7 void mul_mat(int a[][maxn],int b[][maxn]) 8 { 9 memset(tmp,0,sizeof(tmp)); 10 for (int i=0;i<id;i++) 11 for (int j=0;j<id;j++) 12 for (int k=0;k<id;k++) 13 tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j]%p)%p; 14 memcpy(a,tmp,sizeof(tmp)); 15 } 16 void ksm() 17 { 18 for (int i=0;i<id;i++) 19 ans[i][i]=1; 20 int tt=t; 21 while (tt) 22 { 23 if (tt&1) mul_mat(ans,bb); 24 mul_mat(bb,bb); 25 tt>>=1; 26 } 27 } 28 int main () 29 { 30 char c; 31 cin>>n>>t; 32 id=n*9; 33 for (int i=0;i<n;i++) 34 { 35 for (int j=0;j<8;j++) 36 bb[i*9+j][i*9+j+1]=1; 37 for (int j=0;j<n;j++) 38 { 39 cin>>c; 40 c-='0'; 41 if (c) bb[i*9+c-1][j*9]=1; 42 } 43 } 44 ksm(); 45 cout<<ans[0][(n-1)*9]; 46 }