原题:https://www.luogu.org/problemnew/show/P3758
题解:首先要明确一个事情,如果把图放进邻接矩阵时,记矩阵为A,A^k所对应的mat[i][j]就是从i-j经过k步的方案。因为矩阵乘法的定义是这样的:。对于这道题来说就是i->j的路径条数。那么这道题有三种情况,不动,爆炸,移动。
不动的可以在邻接矩阵中自连,爆炸就把每个点连到0,0不能连向任何位置。
#include<bits/stdc++.h>
using namespace std;
const int M=2017;
int L=30,n,m,t;
struct Matrix{//矩阵倍增的模板
int mat[31][31];
Matrix(){
memset(mat,0,sizeof mat);
for(int i=0;i<=L;i++) mat[i][i]=1;
}
friend Matrix operator * (const Matrix &x,const Matrix &y){
Matrix ret;memset(ret.mat,0,sizeof ret.mat);
for(int i=0;i<=L;i++){
for(int j=0;j<=L;j++)
for(int k=0;k<=L;k++) ret.mat[i][j]=(ret.mat[i][j]+x.mat[i][k]*y.mat[k][j])%M;
}
return ret;
}
friend Matrix operator ^ (Matrix &x,int y){
Matrix ret= Matrix();int b=y;
while(b){
if(b&1) ret=ret*x;
b>>=1; x=x*x;
}
return ret;
}
};
int main(){
// freopen("TJOI2017.in","r",stdin);
scanf("%d%d",&n,&m);
Matrix A =Matrix();
for(int i=1,u,v;i<=m;i++){
scanf("%d%d",&u,&v);
A.mat[u][v]=1;A.mat[v][u]=1;
}
for(int i=0;i<=n;i++) A.mat[i][i]=1,A.mat[i][0]=1;
scanf("%d",&t);
A=A^t;
int ans=0;
for(int i=0;i<=n;i++) ans=(ans+A.mat[1][i])%M;
printf("%d\n",ans);
return 0;
}