Time Limit: 10 Sec
Memory Limit: 162 MB
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的余数。
HINT
30%的数据,满足 2 <= N <= 5 ; 1 <= T <= 30 。
100%的数据,满足 2 <= N <= 10 ; 1 <= T <= 1000000000 。
题目分析
如果边权只有1的话就是非常简单的矩阵dp
d
p
[
i
]
[
u
]
dp[i][u]
dp[i][u]表示恰好在i时刻到达u的方案数
d
p
[
i
]
[
u
]
=
∑
d
p
[
i
]
[
v
]
dp[i][u]=\sum dp[i][v]
dp[i][u]=∑dp[i][v](存在
v
→
u
v\rightarrow u
v→u的有向边)
考虑边权不一定为1的情况
注意到边权只有1~9
所以直接把每个点拆成9个点
对于边权为
i
i
i的
u
→
v
u\rightarrow v
u→v的有向边
将其转化为边权为1的
u
i
→
v
1
u_i\rightarrow v_1
ui→v1的有向边
即u拆点后的第i个点到v的第一个点
初始化
d
p
[
0
]
[
1
1
]
=
1
dp[0][1_1]=1
dp[0][11]=1
最后
a
n
s
=
d
p
[
t
]
[
n
1
]
ans=dp[t][n_1]
ans=dp[t][n1]
由于递推方程是线性的,而且t很大,所以矩阵优化DP
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long lt;
lt read()
{
lt f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return x*f;
}
const int mod=2009;
const int maxn=150;
lt n,t;
char ss[maxn];
struct matrix
{
lt mat[maxn][maxn],row,col;
matrix(int r=0,int c=0){
row=r; col=c;
for(int i=1;i<=row;++i)
for(int j=1;j<=col;++j)
mat[i][j]=0;
}
};
matrix operator *(matrix a,matrix b){
matrix c=matrix(a.row,b.col);
for(int i=1;i<=a.row;++i)
for(int j=1;j<=b.col;++j)
for(int k=1;k<=a.col;++k)
{
c.mat[i][j]+=a.mat[i][k]*b.mat[k][j]%mod;
c.mat[i][j]%=mod;
}
return c;
}
matrix qpow(matrix a,lt k)
{
matrix res=matrix(a.row,a.col);
for(int i=1;i<=a.row;++i) res.mat[i][i]=1;
while(k){
if(k&1) res=res*a;
a=a*a; k>>=1;
}
return res;
}
int main()
{
n=read();t=read();
matrix h=matrix(9*n,9*n);
for(int i=1;i<=n;++i)
{
scanf("%s",ss+1);
for(int j=1;j<=n;++j)
{
if(ss[j]=='0') continue;
else h.mat[(i-1)*9+ss[j]-'0'][(j-1)*9+1]=1;
}
}
for(int i=1;i<=n;++i)
for(int j=1;j<=8;++j)
h.mat[(i-1)*9+j][(i-1)*9+j+1]=1;
matrix f=matrix(1,9*n); f.mat[1][1]=1;
matrix res=f*qpow(h,t);
printf("%d",res.mat[1][(n-1)*9+1]);
return 0;
}