都市环游

【问题描述】
因为 SJY 干的奇怪事情过多, SJY 收到了休假的通知,于是他准备在都市间
来回旅游。SJY 有一辆车子,一开始行驶性能为 0,每过 1 时间行驶性能就会提
升 1 点。每个城市的道路都有性能要求。SJY 一共有 t 时间休息,一开始他位于
1 号城市(保证 1 号城市道路要求为 0),他希望在 n 号城市结束旅程。每次穿过
一条城市间的路会花费 1 时间,当然他也可以停留在一个城市不动而花费 1 时间。
当且仅当车子的行驶性能大于等于一个城市,我们才能到达那里。 SJY 希望知道,
旅游的方案模 10086 后的答案。(只要在某一时刻通过的道路存在一条不相同,
就算不同的方案)

【数据规模和约定】
对于 20%的数据,n<=10,t<=80;
对于 50%的数据,n<=30,t<=80;
对于 100%的数据,n<=70,m<=1000,t<=100000000,hi<=70。

 

题解:

对于有限制的t<=70, 直接暴力dp求出即可

然后建立矩阵,矩阵快速幂求解:

对于辅助矩阵,直接按输入的边弄成邻接矩阵即可,注意对角线要为1

然后就是把dp数组作为要求的矩阵的第一行,然后对角线赋值为1即可

 

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #define RG register
 8 #define il inline
 9 using namespace std;
10 const int N=75,M=75,mod=10086,E=5005;
11 int n,m,t,lim[N];
12 struct edge{
13     int x,y;
14 }e[M];
15 int nxt[E<<1],to[E<<1],head[N],num=0,f[N][N];
16 void init(int x,int y){
17     nxt[++num]=head[x];to[num]=y;head[x]=num;
18 }
19 struct mat{
20     int a[N][N];
21     mat(){for(int i=0;i<N;i++)for(int j=0;j<N;j++)a[i][j]=0;}
22     //mat(int b[N][N]){for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)a[i][j]=b[i][j];}
23     mat operator *(const mat &fc){
24         mat tmp;
25         for(RG int i=1;i<=n;i++){
26             for(RG int j=1;j<=n;j++){
27                 tmp.a[i][j]=0;
28                 for(RG int k=1;k<=n;k++){
29                     tmp.a[i][j]+=(a[i][k]*fc.a[k][j]%mod),tmp.a[i][j]%=mod;
30                 }
31             }
32         }
33         return tmp;
34     }
35 };
36 void work()
37 {
38     scanf("%d%d%d",&n,&m,&t);
39     for(int i=1;i<=n;i++)scanf("%d",&lim[i]);
40     for(int i=1;i<=m;i++){
41         scanf("%d%d",&e[i].x,&e[i].y);
42         init(e[i].x,e[i].y);
43     }
44     int u;
45     f[1][0]=1;
46     for(int i=1;i<=70;i++){
47         for(int j=1;j<=n;j++){
48             f[j][i]+=f[j][i-1];
49             if(f[j][i]>=mod)f[j][i]-=mod;
50             if(f[j][i]==0)continue;
51             for(int k=head[j];k;k=nxt[k]){
52                 u=to[k];
53                 if(i>=lim[u])
54                 {
55                     u=to[k];
56                     f[u][i]+=f[j][i-1];
57                     if(f[u][i]>=mod)f[u][i]-=mod;
58                 }
59             }
60         }
61     }
62     if(t<=70){
63         printf("%d\n",f[n][t]);
64         return ;
65     }
66     t-=70;
67     mat S,T;
68     for(int i=1;i<=n;i++)S.a[1][i]=f[i][70];
69     for(int i=2;i<=n;i++)S.a[i][i]=1,T.a[i][i]=1;
70     T.a[1][1]=1;
71     for(int i=1;i<=m;i++)T.a[e[i].x][e[i].y]++;
72     while(t){
73         if(t&1)S=S*T;
74         T=T*T;t>>=1;
75     }
76     printf("%d\n",S.a[1][n]);
77 }
78 int main()
79 {
80     freopen("travel.in","r",stdin);
81     freopen("travel.out","w",stdout);
82     work();
83     return 0;
84 }

 

posted @ 2017-08-17 21:24  PIPIBoss  阅读(181)  评论(0编辑  收藏  举报