题目描述
加里敦星球的人们特别喜欢喝可乐。因而,他们的敌对星球研发出了一个可乐机器人,并且放在了加里敦星球的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:
3 2
1 2
2 3
2
输出样例#1:
8
说明
【样例解释】
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。
Solution:
本题矩阵快速幂。
一个显然的dp思路就是由当前点的方案数向所到点转移,那么我们可以构建一个邻接矩阵:
1、对于边$u\rightarrow v$,令$w[u][v]=w[v][u]=1$。
2、对于停在原地,令$w[u][u]=1$。
3、对于自爆,构建不和其他点联通的虚点$0$,建单向边$w[u][0]=1$。
然后只需要跑下矩阵快速幂就好了。
代码:
/*Code by 520 -- 10.11*/
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
using namespace std;
const int N=,mod=;
struct matrix{
int a[N][N],r,c;
il void clr(){memset(a,,sizeof(a));}
}ans,tp;
int tot,n,m,t; il matrix mul(matrix x,matrix y){
matrix tp; tp.clr();
tp.r=x.r,tp.c=y.c;
For(i,,x.r) For(j,,y.c) For(k,,x.c)
tp.a[i][j]=(tp.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod;
return tp;
} int main(){
scanf("%d%d",&n,&m); int u,v;
ans.r=,ans.c=n; tp.r=n,tp.c=n;
For(i,,m) scanf("%d%d",&u,&v),tp.a[u][v]=tp.a[v][u]=;
For(i,,n) tp.a[i][]=,tp.a[i][i]=;
ans.a[][]=;
scanf("%d",&t);
while(t){
if(t&) ans=mul(ans,tp);
t>>=,tp=mul(tp,tp);
}
For(i,,n) tot=(tot+ans.a[][i])%mod;
cout<<tot;
return ;
}