https://www.luogu.com.cn/problem/P3758
两种思路:
①考虑邻接矩阵的幂对于图的意义。矩阵乘法定义如下。
所以矩阵的2次幂 就相当于此矩阵在2秒后的移动状态。
②分层图dp(这个我还不咋会),然后那个转移方程可以用矩阵乘法来加速运算,从而达到优化。那个矩阵推出来是邻接矩阵。(我还不会推。推出来想必很好的。可以更好的理解这个题)
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int siz=40;
const ll mod=2017;
// 矩阵快速幂啊,和快速幂一个思路。二进制真是一个好东西。
//以前我觉得我很会二进制,结果前几天揹包的二进制优化都忘记了。很多东西都是自以为是,自误以久,应该改正。
struct Mat{
ll mat[siz+1][siz+1];
};
Mat operator *(Mat a,Mat b){
Mat rel;
//memset(rel.mat,0,sizeof(rel.mat));
for(int i=1;i<=siz;i++){
for(int j=1;j<=siz;j++){
rel.mat[i][j]=0;
for(int k=1;k<=siz;k++){
rel.mat[i][j]=((a.mat[i][k]*b.mat[k][j])%mod+rel.mat[i][j])%mod;
}
}
}
return rel;
}
Mat operator^(Mat a,int n){
Mat rel;
memset(rel.mat,0,sizeof(rel.mat));
for(int i=1;i<=siz;i++)rel.mat[i][i]=1;
while(n){
int jud=n&1;
if(jud)rel=rel*a;
a=a*a;
n>>=1;
}
return rel;
}
void show_detai(Mat x,int m){
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++)
cout<<x.mat[i][j]<<" ";
cout<<endl;
}
}
void work_fbnq(){
Mat x;
x.mat[1][1]=1;
x.mat[1][2]=2;
x.mat[2][1]=1;
x.mat[2][2]=2;
Mat rel;
rel=x^2;
/*for(int i=1;i<=2;i++){
for(int j=1;j<=2;j++)
cout<<rel.mat[i][j]<<" ";
cout<<endl;
}*/
}
int main()
{ int m,n,t,a,b;
Mat rel;
memset(rel.mat,0,sizeof(rel.mat));
cin>>m>>n;
for(int i=1;i<=n;i++){
cin>>a>>b;
rel.mat[a][b]=1;
rel.mat[b][a]=1;
}
for(int i=1;i<=m+1;i++)rel.mat[i][i]=1,rel.mat[i][m+1]=1;
cin>>t;
Mat re=rel^(t);
int sum=0;
for(int i=1;i<=(m+1);i++)
sum=(sum+re.mat[1][i])%mod;
cout<<sum<<endl;
return 0;
}