[ABC271G] Access Counter 题解
[ABC271G] Access Counter 题解
思路
挺难的 DP。
状态里面不能含有天数,只能从时间点入手,一眼矩阵快速幂所以考虑以登录次数作为阶段设计状态。
可以得到这个DP:\(g_{i ,j}\) 表示登录 \(i\) 次,且第 \(i\) 次登录在 \(j\) 时刻的概率。
转移可以考虑枚举上一个登录的时间点,注意到上一次登录可能在几天前,所以令 \(f(i, j)\) 表示上一次在 \(i\) 时登录这一次在 \(j\) 时登录的概率:
\[g_{i, j} =\sum_{k = 1}^{24}g_{i - 1, k}\times f(k, j)
\]
考虑求 \(f(i, j)\),可以枚举之间间隔了多少天,如果登录时间差不超过一天,容易处理出 \(w(i, j)\) 表示一天内,\(i + 1\) 时到 \(j - 1\) 时没人登录的概率。
\[\begin{aligned}
f_{i, j} = \sum_{k = 0}^{\infty}P^kw(i, j)p_j\\
f_{i ,j} = w(i ,j)p_j\sum_{k = 0}^{\infty}P^k\\
f_{i ,j} = \dfrac{w(i ,j)p_j}{1 - P}
\end{aligned}
\]
然后矩阵快速幂优化 \(g\) 的转移就可以了。
时间复杂度:\(O(h^3\log n)\),\(h = 24\)。
// Problem: [ABC271G] Access Counter
// Contest: Luogu
// Author: Moyou
// Copyright (c) 2023 Moyou All rights reserved.
// Date: 2024-01-02 22:24:40
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 25, mod = 998244353;
struct Mat {
int m[N][N], r, c;
void clear(int R, int C) {
memset(m, 0, sizeof m);
r = R, c = C;
}
void init() {
for (int i = 1; i <= min(r, c); i++)
m[i][i] = 1;
}
friend Mat operator*(const Mat a, const Mat b) {
Mat res; res.clear(a.r, b.c);
for (int k = 1; k <= a.c; k++)
for (int i = 1; i <= a.r; i++)
for (int j = 1; j <= b.c; j++)
res.m[i][j] = (res.m[i][j] + 1ll * a.m[i][k] * b.m[k][j] % mod) % mod;
return res;
}
void print() {
for(int i = 1; i <= r; i ++, cout << endl)
for(int j = 1; j <= c; j ++)
cout << m[i][j] << ' ';
}
} M, A;
Mat qmi(Mat a, ll b) {
Mat res; res.clear(a.r, a.c), res.init();
while(b) {
if(b & 1) res = res * a;
b >>= 1;
a = a * a;
}
return res;
}
int qmi(int a, ll b) {
int res = 1;
while(b) {
if(b & 1) res = 1ll * res * a % mod;
b >>= 1, a = 1ll * a * a % mod;
}
return res;
}
ll n;
int px, py, p[N], w[N][N], pall;
string s;
int f(int i, int j) {
return 1ll * w[i][j] * p[j] % mod * qmi((1ll - pall + mod) % mod, mod - 2) % mod;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> px >> py >> s;
pall = 1;
px = 1ll * px * qmi(100, mod - 2) % mod, py = 1ll * py * qmi(100, mod - 2) % mod;
for(int i = 1; i <= 24; i ++) {
p[i] = (s[i - 1] == 'T' ? px : py);
pall = 1ll * pall * (1ll - p[i]) % mod;
}
for(int i = 1; i <= 24; i ++) {
for(int j = 1; j <= 24; j ++) {
int tmp = 1;
for(int k = i % 24 + 1; k != j; k = k % 24 + 1) tmp = 1ll * tmp * (1ll - p[k]) % mod;
w[i][j] = tmp;
}
}
M.clear(24, 24), A.clear(24, 1);
for(int i = 1; i <= 24; i ++)
for(int j = 1; j <= 24; j ++)
M.m[i][j] = f(j, i);
A.m[24][1] = 1;
A = qmi(M, n) * A;
int ans = 0;
for(int i = 1; i <= 24; i ++)
if(s[i - 1] == 'A') ans = (1ll * ans + A.m[i][1]) % mod;
cout << (ans + mod) % mod << '\n';
return 0;
}