[ABC271G] Access Counter 题解

[ABC271G] Access Counter 题解

思路

挺难的 DP。

状态里面不能含有天数,只能从时间点入手,一眼矩阵快速幂所以考虑以登录次数作为阶段设计状态。

可以得到这个DP:gi,j 表示登录 i 次,且第 i 次登录在 j 时刻的概率。

转移可以考虑枚举上一个登录的时间点,注意到上一次登录可能在几天前,所以令 f(i,j) 表示上一次在 i 时登录这一次在 j 时登录的概率:

gi,j=k=124gi1,k×f(k,j)

考虑求 f(i,j),可以枚举之间间隔了多少天,如果登录时间差不超过一天,容易处理出 w(i,j) 表示一天内,i+1 时到 j1 时没人登录的概率。

fi,j=k=0Pkw(i,j)pjfi,j=w(i,j)pjk=0Pkfi,j=w(i,j)pj1P

然后矩阵快速幂优化 g 的转移就可以了。

时间复杂度:O(h3logn)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;
}

posted @   MoyouSayuki  阅读(209)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2023-01-02 [NOI2018] 归程 题解
:name :name
点击右上角即可分享
微信分享提示