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 }

 

posted @ 2021-03-03 10:47  acmloser  阅读(61)  评论(0编辑  收藏  举报