[TJOI2017]可乐

题目描述

加里敦星球的人们特别喜欢喝可乐。因而,他们的敌对星球研发出了一个可乐机器人,并且放在了加里敦星球的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^9。

设f[i][j][0/1]表示i时刻,j地,是否爆炸

f[i][j][0]=∑f[i-1][k][0]+f[i-1][j][0]

f[i][j][1]=f[i-1][j][1]+f[i-1][j][0]

但直接dp显然超时,考虑用矩阵

(s0,s1,s2,s3.....)

s0为已爆炸的方案,s1表示到1的方案

转移:

s0=s0'+s1'+s2'......+sn'

s1=s1'+sk'

.....

所以可以写成一个(n+1)*(n+1)的矩阵

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct Matrix
{
long long a[][];
}Mat,pre,ans;
int n,m,t;
long long s;
Matrix operator *(const Matrix &x,const Matrix &y)
{
Matrix res;
int i,j,k;
memset(res.a,,sizeof(res.a));
for (i=;i<=n;i++)
{
for (j=;j<=n;j++)
{
for (k=;k<=n;k++)
res.a[i][j]+=x.a[i][k]*y.a[k][j];
res.a[i][j]%=;
}
}
return res;
}
void qpow(int x)
{int i;
for (i=;i<=n;i++)
ans.a[i][i]=;
while (x)
{
if (x&) ans=ans*Mat;
Mat=Mat*Mat;
x/=;
}
}
int main()
{int x,y,i;
cin>>n>>m;
for (i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
Mat.a[x][y]=;
Mat.a[y][x]=;
}
cin>>t;
for (i=;i<=n;i++)
Mat.a[i][i]=;
for (i=;i<=n;i++)
Mat.a[i][]=;
memset(pre.a,,sizeof(pre.a));
qpow(t);
pre.a[][]=;
ans=pre*ans;
for (i=;i<=n;i++)
s+=ans.a[][i],s%=;
cout<<s;
}
上一篇:JPush删除别名及回调函数(SWIFT)


下一篇:词频统计 List Array