题目描述
加里敦星球的人们特别喜欢喝可乐。因而,他们的敌对星球研发出了一个可乐机器人,并且放在了加里敦星球的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。
想法
很显然的dp
n这么小,可以矩阵加速
进行快速幂的矩阵共n+1列,前n列为某个点与其他点的连接情况,最后一列全是1,计算某一秒自爆的方案数
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define P 2017
using namespace std;
const int N = 35;
struct matrix{
int a[N][N];
void clear(){
for(int i=1;i<N;i++)
for(int j=1;j<N;j++)
a[i][j]=(i==j);
}
matrix operator * (const matrix &b) const{
matrix c;
for(int i=1;i<N;i++)
for(int j=1;j<N;j++){
c.a[i][j]=0;
for(int k=1;k<N;k++)
c.a[i][j]=(c.a[i][j]+(a[i][k]*b.a[k][j])%P)%P;
}
return c;
}
};
int n,m,t;
matrix map;
matrix pow_mod(matrix b,int x){
matrix ret;
ret.clear();
while(x){
if(x&1) ret=ret*b;
b=b*b;
x>>=1;
}
return ret;
}
int main()
{
int u,v;
scanf("%d%d",&n,&m);
map.clear();
for(int i=0;i<m;i++){
scanf("%d%d",&u,&v);
map.a[u][v]=map.a[v][u]=1;
}
for(int i=1;i<=n+1;i++)
map.a[i][n+1]=1;
scanf("%d",&t);
matrix a;
memset(a.a,0,sizeof(a.a));
a.a[1][1]=1;
a=a*pow_mod(map,t);
int ans=0;
for(int i=1;i<=n+1;i++)
ans=(ans+a.a[1][i])%P;
printf("%d\n",ans);
return 0;
}