P4159 [SCOI2009] 迷路
考察:dp+矩阵快速幂
思路:
首先了解邻接矩阵的一个性质:当邻接矩阵Tk , aij表示从i到j长度为k的路径数有aij条.以k = 2为例,aij*ajk 表示从i->j有一条路,从j->k有一条路.总体就是i->k有一条路.当j变化时就能得到方案数.
但是这道题的边权并非为1,这个性质只能用于边权为1的情况.因此我们要让边权化为1.这里要想到拆点,将一个点i,拆成1~9点(此题边权不超过9,便于处理.)起点是1,如果路径长度为5,那么在i的第5个点和j的第一个点连一条边.
注意:路径为0是不用连的
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 typedef long long LL; 6 const int Mod = 2009,N = 110; 7 int g[N][N],a[N][N],n,t; 8 char s[15]; 9 void mul(int f[][N],int a[][N]) 10 { 11 int res[N][N],all = n*9; 12 memset(res,0,sizeof res); 13 for(int i=1;i<=all;i++) 14 for(int j=1;j<=all;j++) 15 for(int k=1;k<=all;k++) 16 res[i][j] = ((LL)f[i][k]*a[k][j]%Mod+res[i][j])%Mod; 17 memcpy(f,res,sizeof res); 18 } 19 int main() 20 { 21 scanf("%d%d",&n,&t); 22 for(int i=1;i<=n;i++) 23 { 24 for(int j=1;j<=8;j++) 25 g[(i-1)*9+j][(i-1)*9+j+1] = 1; 26 scanf("%s",s+1); 27 for(int j=1;j<=n;j++) 28 if(s[j]>'0') 29 g[(i-1)*9+s[j]-'0'][(j-1)*9+1] = 1; 30 } 31 memcpy(a,g,sizeof g); 32 t--; 33 while(t) 34 { 35 if(t&1) mul(g,a); 36 mul(a,a); 37 t>>=1; 38 } 39 printf("%d\n",g[1][(n-1)*9+1]); 40 return 0; 41 }