设f[i][j][1]表示第i秒停在j上没有爆炸的方案数,设f[i][j][0]表示第i秒停在j上的总方案数。
f[i][j][1]=f[i-1][j][1]+f[i-1][k][1]
f[i][j][0]=f[i-1][j][0]+f[i-1][j][1]+f[i-1][k][1]
然后我们发现这是一个一阶递推,所以直接矩阵转一转就好了!
PS:我可能对我那套矩阵理论有些。。不放心啊?我已开始傻逼地设了一个n行2列的矩阵,发现死活构造不出那个旋转因子(因为f[][][0]要同时去取f’[][][0]和f’[][][1])后来发现我真的傻,直接构造成一个2n行1列的矩阵不就好了。。。
注意一下初始化。
#include<cmath>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<iomanip>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1000000000
#define mo 2017
#define N 200
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
int n,m,i,j,t,ans;
int res[N],p[N],g[N][N],pp[N][N],x[N],y[N];
void mlt1()
{
int i,j;
fo(i,1,n) p[i] = res[i] , res[i] = 0;
fo(i,1,n)
fo(j,1,n)
res[i]=(res[i]+1ll*g[i][j]*p[j]%mo)%mo;
}
void mlt2()
{
int i,j,k;
fo(i,1,n) fo(j,1,n) pp[i][j] = g[i][j] , g[i][j] = 0;
fo(i,1,n)
fo(j,1,n)
fo(k,1,n)
g[i][j]=(g[i][j]+1ll*pp[i][k]*pp[k][j]%mo)%mo;
}
int main()
{
cin>>n>>m;
fo(i,1,m) cin>>x[i]>>y[i];
cin>>t;
fo(i,1,n) g[i][i] = g[i][n+i] = 1;
fo(i,n+1,n+n) g[i][i] = 1;
fo(i,1,m) g[x[i]][n+y[i]] = g[y[i]][n+x[i]] = 1;
fo(i,1,m) g[n+x[i]][n+y[i]] = g[n+y[i]][n+x[i]] = 1;
res[1] = res[n+1] = 1; n = n * 2;
while (t)
{
if (t&1) mlt1();
mlt2(); t >>= 1;
}
fo(i,1,n/2) ans = (ans + res[i]) % mo;
cout<<ans<<endl;
return 0;
}