都市环游
【问题描述】
因为 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 }