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。
//written by zzy
题目大意:
给你个图,有
n
n
n个城市,
m
m
m条边,每个城市至少要第
h
[
i
]
h[i]
h[i]时间后才能经过,
走一条边或呆在当前城市里都会花费时间
1
1
1,
求在第
t
t
t时间时到第
n
n
n城市的方案数。
题解:
对于50%的数据,
n
<
=
30
,
t
<
=
80
n<=30,t<=80
n<=30,t<=80,可以考虑dp,
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]表在第
i
i
i 时间到第
j
j
j 城市的方案数,
a
[
i
]
[
j
]
a[i][j]
a[i][j]表读入时城市
i
i
i 到城市
j
j
j 的方案数
易推
f
[
i
]
[
j
]
=
∑
f
[
i
−
1
]
[
k
]
∗
a
[
k
]
[
j
]
,
(
1
<
=
k
<
=
n
)
f[i][j]=∑f[i-1][k]*a[k][j],(1<=k<=n)
f[i][j]=∑f[i−1][k]∗a[k][j],(1<=k<=n) //从在第
i
i
i 时间从城市
k
k
k 到城市
j
j
j
考虑满分作法,
发现
h
[
i
]
<
=
70
h[i]<=70
h[i]<=70 ,即在第
70
70
70 时间后没有限制,可以随便走,
那么每次矩阵
f
f
f 都会乘上矩阵
a
a
a,
(
a
∗
a
[
i
,
j
]
=
∑
a
[
i
,
k
]
∗
a
[
k
,
j
]
a*a~[i,j]~=∑a[i,k]*a[k,j]
a∗a [i,j] =∑a[i,k]∗a[k,j],即枚举
k
k
k ,从
i
i
i 到
k
k
k 再走到
j
j
j 的方案数,
也即走两个时间从
i
i
i 到
j
j
j 的方案数
那么
a
t
a^t
at 即走
t
t
t 个时间从
i
i
i 到
j
j
j 的方案数)
用dp处理前
70
70
70 时间和用矩阵快速幂后
70
70
70 的时间
因为矩阵乘法有结合律
再令
f
f
f 与 ·at-70 相乘,
答案为
f
[
t
+
1
]
[
n
]
f[t+1][n]
f[t+1][n]
#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 75
#define T 85
#define Mod 10086
using namespace std;
int i,j,k,n,l,t,x,y;
int h[N],f[T][N];
struct Mal{
long long m[N][N];
};
Mal a,b,ans;
Mal mult(Mal x,Mal y) {
Mal re;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
re.m[i][j]=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
for (int k=1;k<=n;k++)
re.m[i][j]=(re.m[i][j]+(x.m[i][k]*y.m[k][j])%Mod)%Mod;
return re;
}
void mal_ksm(long long p) {
for (int i=1;i<=n;i++)
ans.m[i][i]=1;
while (p) {
if (p&1) ans=mult(ans,a);
p>>=1;
a=mult(a,a);
}
}
int main()
{
scanf("%d%d%d",&n,&l,&t);
for (i=1;i<=n;i++)
scanf("%d",&h[i]);
for (i=1;i<=l;i++) {
scanf("%d%d",&x,&y);
a.m[x][y]++;
}
f[0][1]=1;
for (i=1;i<=n;i++) a.m[i][i]=1;
for (i=1;i<=min(t,70);i++)
for (j=1;j<=n;j++)
if (h[j]<=i)
for (k=1;k<=n;k++)
f[i][j]=(f[i][j]+(f[i-1][k]*a.m[k][j])%Mod)%Mod;
if (t<=70) {
printf("%d",f[t][n]); return 0;
}
mal_ksm(t-70);
a=ans;
for (j=1;j<=n;j++)
for (k=1;k<=n;k++)
f[71][j]=(f[71][j]+(f[70][k]*a.m[k][j])%Mod)%Mod;
printf("%d",f[71][n]);
}