题目:
题意:
给出一张图,每个点都需要有一定的性能才能前往,而性能会随着时间的增加而增加,问最后在 n n n号城市的方案有多少
分析:
因为到达任意城市的性能要求最多不过
70
70
70,所以我们可以对答案进行分段
一个求前
70
70
70的时间的答案,因为此时有些路径是不能走的,所以我们用
d
p
dp
dp来求解,设
f
i
,
j
f_{i,j}
fi,j表示在
i
i
i这个时刻,到达
j
j
j号城市有多少种方案
另一个求后
70
70
70到
t
t
t的答案,因为所有边都是可以任意走的,所以我们用矩阵乘法来快速求解,同时因为我们可以待在一个城市不动,所以我们也需要给同一个城市标记为
1
1
1再进行矩阵乘法
代码:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
#define LL long long
#define mo 10086
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
struct node{
LL x,y;
}e[5005];
LL w[75];
LL f[75][75],tf[75][75],n=read(),m=read(),t=read();
struct wzd{
LL a[75][75];
wzd operator * (wzd &x)
{
wzd sum;
memset(sum.a,0,sizeof(sum.a));
for(LL i=1;i<=n;i++)
for(LL j=1;j<=n;j++)
for(LL k=1;k<=n;k++)
sum.a[i][j]=(1ll*sum.a[i][j]+a[i][k]%mo*x.a[k][j]%mo)%mo;
return sum;
}
}a,b;
int main()
{
LL mm=m;m=0;
for(LL i=1;i<=n;i++) w[i]=read();
for(LL i=1;i<=mm;i++)
{
LL x=read(),y=read();
tf[x][y]++;
if(tf[x][y]>1) continue;
e[++m].x=x;e[m].y=y;
}
f[0][1]=1;
for(LL i=1;i<=70;i++)
{
for(LL j=1;j<=n;j++) f[i][j]=f[i-1][j];
for(LL j=1;j<=m;j++)
if(i>=w[e[j].y]) (f[i][e[j].y]+=f[i-1][e[j].x]*tf[e[j].x][e[j].y])%=mo;
}
if(t<=70) return !printf("%lld",f[t][n]);
for(LL i=1;i<=n;i++) a.a[1][i]=f[70][i],b.a[i][i]=1;
for(LL i=1;i<=m;i++) b.a[e[i].x][e[i].y]=tf[e[i].x][e[i].y];
t-=70;
while(t)
{
if(t&1) a=a*b;
b=b*b;t>>=1;
}
printf("%lld",a.a[1][n]);
return 0;
}