JZOJ 1036. 【SCOI2009】迷路

题目

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

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 } 

 

posted @ 2019-08-11 11:30  Melted_czj  阅读(165)  评论(0编辑  收藏  举报
body { background-color:whitesmoke; } // 修改背景颜色为半透明 #home,#sideBarMain>div,#blog-sidecolumn>div>div,.catListView{ background-color:rgba(255,255,255,0); } // 修改其他边框的颜色