BZOJ-4887 [Tjoi2017]可乐(邻接矩阵的幂)
题目描述
有一个 \(n(1\leq n\le 30)\) 个点 \(m(0< m\leq 100)\) 条边的无向图,在第 \(0\) 秒,点 \(1\) 有一个机器人,这个机器人有三种行为:停在原地,去下一个相邻的城市,自爆。它每一秒都会随机触发一种行为。问经过了 \(t(1\leq t\leq 10^6)\) 秒,机器人的行为方案数是多少。
分析
停在原地相当于每个点都有一个到本身的自环;自爆相当于去点 \(0\),其他所有点都有连向点 \(0\) 的一条有向边,但点 \(0\) 除了连向自身的自环外没有任何出边,这样满足了任意一个点都可以自爆,且无法恢复到其他状态。对邻接矩阵求 \(t\) 次幂,设结果为 \(A\),答案为 \(\displaystyle\sum_{i=1}^{n}A[1][i]\)。
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,t;
const int mod=2017;
struct matrix
{
int mat[310][310];
matrix()
{
memset(mat, 0, sizeof(mat));
}
}A;
matrix mul(matrix A,matrix B)
{
matrix ans;
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
for(int k=0;k<=n;k++)
ans.mat[i][j]=(ans.mat[i][j]+A.mat[i][k]*B.mat[k][j])%mod;
return ans;
}
matrix matrix_pow(matrix a,int b)
{
matrix ans;
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
ans.mat[i][j]=(i==j);
while(b)
{
if(b&1)
ans=mul(ans,a);
a=mul(a,a);
b>>=1;
}
return ans;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d %d",&x,&y);
A.mat[x][y]=1;
A.mat[y][x]=1;
}
for(int i=0;i<=n;i++)
A.mat[i][i]=1;
for(int i=1;i<=n;i++)
A.mat[i][0]=1;
int ans=0;
cin>>t;
A=matrix_pow(A,t);
for(int i=0;i<=n;i++)
ans=(ans+A.mat[1][i])%mod;
cout<<ans<<endl;
return 0;
}
posted on 2020-11-20 21:47 DestinHistoire 阅读(103) 评论(0) 收藏 举报