BZOJ4887可乐题解--矩阵运算

题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=4887

分析

话说这道题经常见到类似模型来计数算期望,概率啊,然而我太蒻了都不会做,今天看到这题的第一个题解感觉真妙啊

我们构建邻接矩阵$A$,$a[i][j]=1$表示i到j状态有连接的边。

如果有一条边连接$u,v$则$a[u][v]=1$且$a[v][u]=1$

$a[i][i]=1$表示停在原地

再构建一个虚点0,$a[i][0]=1$表示自爆事件,完美满足题目要求

统计$\sum_{i=0}^{N}A[1][i]$就是答案

然而这题BZOJ AC 洛谷 WA 不知道怎么回事

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <cmath>
#include <vector>
#define ll long long
#define ri register int
using namespace std;
const int maxn=35;
const int maxm=105;
const int inf=0x7ffffff;
template <class T>inline void read(T &x){
x=0;int ne=0;char c;
while(!isdigit(c=getchar()))ne=c=='-';
x=c-48;
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
x=ne?-x:x;
return ;
}
int n,m,t;
struct Mat{
int mat[maxn][maxn];
Mat(){memset(mat,0,sizeof(mat));}
Mat(int x){for(ri i=0;i<=n;i++)mat[i][i]=x;}
Mat operator *(const Mat &b)const {
Mat ans;
for(ri i=0;i<=n;i++){
for(ri j=0;j<=n;j++){
for(ri k=0;k<=n;k++){
ans.mat[i][j]+=mat[i][k]*b.mat[k][j]%2017;
}
}
}
return ans;
}
Mat operator ^(const int & C)const {
Mat ans=Mat(1),res=*this;int c=C;
while(c){
if(c&1)ans=ans*res;
res=res*res;
c=c>>1;
}
return ans;
}
}a;

int main(){
int x,y,ans=0;
read(n),read(m);
for(ri i=0;i<=n;i++){
a.mat[i][0]=1;
a.mat[i][i]=1;
}
for(ri i=1;i<=m;i++){
read(x),read(y);
a.mat[x][y]=a.mat[y][x]=1;
}
read(t);
a=a^t;
for(ri i=0;i<=n;i++)ans+=a.mat[1][i]%2017;
printf("%d\n",ans%2017);
return 0;
}