题意:
给
n
个点的有向图,经过每条边需要不同时间,求从
题解:
T很大,不能线性递推,n很小,发现每次递推式又一样,很容易想到矩阵快速幂优化dp。
不妨设F[i][j]为第i点当前时间前j秒的方案数,有一下递推式:
1.设边
(u,v,ti)
,则有转移
(减一是因为每次矩阵乘法相当于将时间往后推一秒)
2.对于每个点有转移
ti<=9 。那么把每个点看做9个与时间有关的状态,用矩阵转移即可。所以时间复杂度为 O((9n)3logT) 。
#include<bits/stdc++.h>
using namespace std;
const int Mod=2009;
int n,m,lim;
char ch[5];
struct matrix
{
int a[120][120];
inline void init(int bz)
{
for(int i=0;i<lim;i++)
for(int j=0;j<lim;j++)
this->a[i][j]=0;
if(bz)
{
for(int i=0;i<lim;i++)this->a[i][i]=1;
}
}
friend inline matrix operator *(const matrix &a,const matrix &b)
{
matrix c;c.init(0);
for(int i=0;i<lim;i++)
for(int j=0;j<lim;j++)
for(int k=0;k<lim;k++)
(c.a[i][j]+=(a.a[i][k]*b.a[k][j]))%=Mod;
return c;
}
friend inline matrix operator ^(matrix a,int b)
{
matrix c;c.init(1);
while(b)
{
if(b&1)c=c*a;
a=a*a;
b>>=1;
}
return c;
}
}e,o;
inline int tocode(int x,int y){return x*9+y;}
int main()
{
scanf("%d%d",&n,&m);
lim=n*9;e.init(0);
for(int i=0;i<n;i++)
{
scanf("%s",ch);
for(int j=0;j<n;j++)
{
int t=ch[j]-'0';
if(!t)continue;
e.a[tocode(i,t-1)][tocode(j,0)]=1;
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<8;j++)
{
e.a[tocode(i,j)][tocode(i,j+1)]=1;
}
}
o.init(0);o.a[0][0]=1;
o=o*(e^m);
printf("%d\n",o.a[0][tocode(n-1,0)]);
}