/*离散数学中图论的知识太重用了 一定要去总结总结*/
我们直接重邻接矩阵的的幂的意义思考
邻接矩阵的幂:A的k次方幂矩阵的第i行j列的数字含义是从第i行第j列经过k步的路径方案总数
1.那么对该题目而言就是要求A[1][i]的总和,但是由于题目给出自爆的情况所以我们可以在邻接矩阵的每一个点都像这个点连一条边,这个点除自己外不连其他出边,这样就满足了任意一个点都可以自爆,而且无法恢复到其他状态,那么最后就是求A[0][i]的总和,题目的答案就明朗起来了。
2.其次要求矩阵的幂那么就涉及到了高性能,也就是矩阵的快速幂。对于矩阵的快速幂而言,其核心就是快速幂,但是不同于快速幂,矩阵的快速幂有关于乘的运算要涉及到重载,也是一个值得去深入学习一下的。
#include <bits/stdc++.h>
using namespace std;
const int inf=2017;
struct matrix {
int num[35][35];
matrix(){
memset(num,0,sizeof(num));
}
}mp;
matrix multi(matrix a,matrix b){
matrix c;
for(int i=0;i<=30;i++){
for(int j=0;j<=30;j++){
for(int k=0;k<=30;k++){
c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%inf)%inf;
}
}
}
return c;
}
matrix ksm(matrix a,int b){
matrix c;
for(int i=0;i<=30;i++){
c.num[i][i]=1;
}
while(b){
if(b&1) c=multi(c,a);
a=multi(a,a);
b>>=1;
}
return c;
}
int n,m;
int main(){
cin>>n>>m;
int u,v;
for(int i=1;i<=m;i++){
cin>>u>>v;
mp.num[u][v]=1;
mp.num[v][u]=1;
}
for(int i=1;i<=n;i++) mp.num[i][i]=1;
for(int i=0;i<=n;i++) mp.num[i][0]=1;
int ans=0;
int t;
cin>>t;
matrix p=ksm(mp,t);
for(int i=0;i<=n;i++) ans=(ans+p.num[1][i])%inf;
cout<<ans<<endl;
return 0;
}
关于对矩阵的快速幂将会有如下解释
struct matrix {
int num[35][35];
matrix(){
memset(num,0,sizeof(num));
}
}mp;
matrix multi(matrix a,matrix b){ //这块就是一个函数来求两个矩阵的乘法
matrix c;
for(int i=0;i<=30;i++){
for(int j=0;j<=30;j++){
for(int k=0;k<=30;k++){
c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%inf)%inf;
}
}
}
return c;
}
matrix ksm(matrix a,int b){//从这块就能一眼看出来 核心就是快速幂算法
matrix c;
for(int i=0;i<=30;i++){
c.num[i][i]=1;
}
while(b){
if(b&1) c=multi(c,a);
a=multi(a,a);
b>>=1;
}
return c;
}
/*
对于矩阵的快速幂的核心算法就是快速幂 读者只需要处理好矩阵与矩阵的乘法就行(不行就当板子来记)
*/