题目描述
加里敦星球的人们特别喜欢喝可乐。因而,他们的敌对星球研发出了一个可乐机器人,并且放在了加里敦星球的1号城市上。这个可乐机器人有三种行为: 停在原地,去下一个相邻的城市,自爆。它每一秒都会随机触发一种行为。现 在给加里敦星球城市图,在第0秒时可乐机器人在1号城市,问经过了t秒,可乐机器人的行为方案数是多少?
输入输出格式
输入格式:
第一行输入两个正整数况N,M,N表示城市个数,M表示道路个数。(1 <= N <=30,0 < M < 100)
接下来M行输入u,v,表示u,v之间有一条道路。(1<=u,v <= n)保证两座城市之间只有一条路相连。
最后输入入时间t
输出格式:
输出可乐机器人的行为方案数,答案可能很大,请输出对2017取模后的结果。
输入输出样例
说明
【样例解释】
1 ->爆炸
1 -> 1 ->爆炸
1 -> 2 ->爆炸
1 -> 1 -> 1
1 -> 1 -> 2
1 -> 2 -> 1
1 -> 2 -> 2
1 -> 2 -> 3
【数据范围】
对于20%的pn,有1 < t ≤ 1000
对于100%的pn,有1 < t ≤ 10^6。
裸的矩阵加速DP
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define rep(i,l,r) for (int i=l; i<=r; i++) 5 using namespace std; 6 7 const int N=2000100,md=2017; 8 struct mat{ int d[100][100]; mat(){ memset(d,0,sizeof(d)); } }a,b,c; 9 int n,m,u,v,t,ans,cnt,h[N],nxt[N],to[N]; 10 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } 11 12 void print(mat b){ rep(i,1,2*n){ rep(j,1,2*n) printf("%3d",b.d[i][j]); printf("\n"); } } 13 14 mat mul(mat a,mat b){ 15 mat res; 16 rep(i,1,2*n) rep(j,1,2*n) rep(k,1,2*n) res.d[i][k]=(res.d[i][k]+a.d[i][j]*b.d[j][k]%md)%md; 17 return res; 18 } 19 20 mat ksm(mat a,int b){ 21 mat res; 22 rep(i,1,2*n) res.d[i][i]=1; 23 for (; b; a=mul(a,a),b>>=1) 24 if (b & 1) res=mul(res,a); 25 return res; 26 } 27 28 int main(){ 29 scanf("%d%d",&n,&m); 30 rep(i,1,m) scanf("%d%d",&u,&v),add(u,v),add(v,u); 31 scanf("%d",&t); a.d[1][1]=a.d[1][n+1]=1; 32 rep(i,1,n){ 33 b.d[i][i]=b.d[i+n][i]=1; 34 for (int j=h[i]; j; j=nxt[j]) b.d[to[j]+n][i]=1; 35 } 36 rep(i,1,n){ 37 b.d[i+n][i+n]=1; 38 for (int j=h[i]; j; j=nxt[j]) b.d[to[j]+n][i+n]=1; 39 } 40 c=mul(a,ksm(b,t)); 41 rep(i,1,n) ans=(ans+c.d[1][i])%md; 42 printf("%d\n",ans); 43 return 0; 44 }