JZOJ 3847. 都市环游(travel)

题目

Description

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

Input

第一行三个数n,m,t,表示有n个城市m条道路t时间。
第二行n个数,hi表示第i个城市的道路性能要求。
第三到m+2行,每行两个数u,v,表示城市u与城市v之间有一条单向道路连接(可能有重边)。

Output

包括一个数字,表示旅游的方案模10086。
 

Sample Input

5 17 7
0 2 4 5 3 
1 2
2 1
1 3
3 1
1 4
4 1
4 5
5 4
5 3
4 1
2 1
5 3
2 1
2 1
1 2
2 1
1 3

Sample Output

245
 

Data Constraint

对于20%的数据,n<=10,t<=80;
对于50%的数据,n<=30,t<=80;
对于100%的数据,n<=70,m<=1000,t<=100000000,hi<=70。

分析

 

  • 首先求这种方案数的图 肯定是可以用矩阵的
  • 但是我们这里还有一个城市的性能限制
  • 不能直接上矩阵
  • 现在我们想可以先把最大的性能值跑出来
  • 后面不就可以随便跑了吗
  • 因为最大是70,所以直接n2不断跟新地图就好了

 

代码

 

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 #define ll long long
 7 #define mod 10086
 8 using namespace std;
 9 int a[101],map[71][71],mp[71][71],f[71],n;
10 int ans,maxn;
11 void mul()
12 {
13     int c[71];
14     memset(c,0,sizeof(c));
15     for (int i=1;i<=n;i++) 
16       for (int j=1;j<=n;j++) 
17         c[i]=(c[i]+(mp[j][i]*f[j])%mod)%mod;
18     for (int i=1;i<=n;i++) f[i]=c[i];
19 }
20 void mull()
21 {
22     int c[71][71];
23     memset(c,0,sizeof(c));
24     for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) for (int k=1;k<=n;k++) c[i][j]=(c[i][j]+(mp[i][k]*mp[k][j])%mod)%mod;
25     for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) mp[i][j]=c[i][j];
26 }
27 int main()
28 {
29     int m,t;
30     scanf("%d%d%d",&n,&m,&t);
31     for (int i=1;i<=n;i++) scanf("%d",&a[i]),maxn=max(a[i],maxn);
32     for (int i=1;i<=n;i++) map[i][i]=1;
33     for (int i=1,x,y;i<=m;i++)
34     {
35         scanf("%d%d",&x,&y);
36         map[x][y]++;
37     }
38     f[1]=1;
39     for (int i=0;i<=min(t,maxn);i++)
40     {
41         for (int j=1;j<=n;j++)
42           if (a[j]==i)
43           {
44                for (int k=1;k<=n;k++)
45                  mp[k][j]=map[k][j];
46           }
47         mul();
48      } 
49      if (maxn>=t) {cout<<f[n];return 0;}
50     int b=t-maxn;
51     while (b)
52     {
53         if(b&1)  mul();
54         b>>=1;
55         mull();
56     }
57     cout<<f[n];
58     return 0;
59 }

 

posted @ 2019-11-08 16:16  Melted_czj  阅读(164)  评论(0编辑  收藏  举报
body { background-color:whitesmoke; } // 修改背景颜色为半透明 #home,#sideBarMain>div,#blog-sidecolumn>div>div,.catListView{ background-color:rgba(255,255,255,0); } // 修改其他边框的颜色