概率论——马尔科夫链
马尔科夫链是一个随机过程,包含一些状态和转移概率,对于每一个状态,我们都知道由这个状态向其他状态转移的概率是多少。
例如,我们考虑处在一个 n n n层楼的一楼,每次我们都有同等概率的上楼或下楼,除非处在一楼或者顶楼。那么 k k k步之后处于 m m m层的概率是多少?
如果 n = 5 n=5 n=5,每一层楼都是一个状态的话,对应的马尔科夫链为:
我们定义向量
V
k
=
[
p
1
,
p
2
,
…
,
p
n
]
V_k=[p_1,p_2,\ldots,p_n]
Vk=[p1,p2,…,pn],为经过
k
k
k步之后,处在
i
i
i层
p
i
p_i
pi的概率向量。
每一个马尔科夫链都对应一个递推矩阵 T T T,使得 V k = T V k − 1 V_k = T V_{k-1} Vk=TVk−1。
例如上述马尔科夫链就可以转换为:
例题
#include <bits/stdc++.h>
using namespace std;
#define FR freopen("in.txt", "r", stdin)
#define FW freopen("out.txt", "w", stdout)
typedef long long ll;
ll mod = 2017;
struct Matrix
{
ll arr[35][35];
int n;
Matrix(int N)
{
n = N;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
arr[i][j] = 0;
}
Matrix operator*(Matrix o)
{
Matrix ans(n);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
ans.arr[i][j] = (ans.arr[i][j] + (arr[i][k] * o.arr[k][j]) % mod) % mod;
return ans;
}
};
Matrix fpow(Matrix a, ll e)
{
Matrix ans(a.n);
for (int i = 1; i <= a.n; i++)
{
ans.arr[i][i] = 1;
}
for (; e; e >>= 1, a = a * a)
{
if (e & 1)
ans = ans * a;
}
return ans;
}
int main()
{
int n, m;
scanf("%d %d", &n, &m);
Matrix T(n + 1);
for (int i = 1; i <= m; i++)
{
int u, v;
scanf("%d %d", &u, &v);
T.arr[u][v] = 1;
T.arr[v][u] = 1;
}
for (int i = 1; i <= n; i++)
{
T.arr[i][i] = 1;
T.arr[n + 1][i] = 1;
}
T.arr[n + 1][n + 1] = 1;
ll t;
scanf("%lld", &t);
T = fpow(T, t);
ll ans = 0;
for (int i = 1; i <= n + 1; i++)
{
ans = (ans + T.arr[i][1]) % mod;
}
printf("%lld", ans);
return 0;
}