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;
}