1 条题解

  • 0
    @ 2025-10-19 11:21:02

    问题分析

    棋盘大小 n×mn \times m,骑士有 88 种走法,每种走法的概率由输入的权重 wiw_i 归一化得到。
    当骑士走出棋盘边界时游戏结束,我们需要求从 (sx,sy)(sx, sy) 出发到出界的期望回合数。


    数学模型

    Ex,yE_{x,y} 表示从格子 (x,y)(x,y) 出发到出界的期望回合数。

    边界条件

    如果 (x,y)(x,y) 已经在棋盘外,则 Ex,y=0E_{x,y} = 0(因为已经结束)。

    转移方程

    对于棋盘内的 (x,y)(x,y),有:

    $$E_{x,y} = 1 + \sum_{k=1}^8 p_k \cdot E_{\text{next}_k(x,y)} $$

    其中 nextk(x,y)\text{next}_k(x,y) 是第 kk 种走法后的新位置。


    线性方程组

    设棋盘内共有 NN 个格子(Nn×mN \le n \times m),我们可以将每个格子编号 1N1 \dots N,建立方程:

    Ei=1+jPijEjE_i = 1 + \sum_{j} P_{i \to j} E_j

    其中 PijP_{i \to j} 是从 ii 走到 jj 的概率。

    整理得:

    EijPijEj=1E_i - \sum_j P_{i \to j} E_j = 1

    这是一个 NN 元线性方程组,可以用高斯消元求解。


    模运算处理

    题目要求模 998244353998244353 意义下的答案,即所有运算在模 998244353998244353 下进行。

    • 概率 pk=wkinv(W)modMp_k = w_k \cdot \text{inv}(W) \bmod M,其中 W=wiW = \sum w_iinv\text{inv} 是模逆元。
    • 高斯消元时除法用模逆元代替。

    算法步骤

    1. 读入 n,m,w[1..8],qn, m, w[1..8], q
    2. 计算总权重 WW,并计算 pk=wkinv(W)modMp_k = w_k \cdot \text{inv}(W) \bmod M
    3. 对棋盘内每个格子 (x,y)(x,y) 分配一个编号 id[x][y]id[x][y]
    4. 建立 N×NN \times N 的系数矩阵 AA 和常数向量 bb
      • 对每个格子 ii
        • A[i][i]=1A[i][i] = 1
        • 对每种走法 kk
          • 计算新位置 (nx,ny)(nx, ny)
          • 如果新位置在棋盘内,则 A[i][id[nx][ny]]A[i][id[nx][ny]] 减去 pkp_k
          • 如果新位置出界,则不影响(E=0E=0
        • b[i]=1b[i] = 1
    5. 高斯消元解 AE=bA \cdot E = b
    6. 对每个询问 (sx,sy)(sx,sy),输出 E[id[sx][sy]]E[id[sx][sy]]

    复杂度分析

    • 棋盘内最多 4000040000 个格子,高斯消元 O(N3)O(N^3) 不可行(N36.4×1013N^3 \approx 6.4 \times 10^{13})。
    • 但注意到每个方程只有 99 个非零系数(11 个对角元 + 最多 88 个转移),是稀疏矩阵。
    • 对于 n,m200n,m \le 200N40000N \le 40000,直接高斯消元不可行,需要优化。

    优化方法

    本题 n,m200n,m \le 200NN 最大 4000040000,直接高斯消元 O(N3)O(N^3) 会超时。
    但骑士的移动是局部且规则的,可以利用带状矩阵特性或迭代法(如高斯-赛德尔迭代)求解。


    代码实现(高斯-赛德尔迭代法)

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int MOD = 998244353;
    const int MAXN = 205;
    
    ll qpow(ll a, ll b) {
        ll res = 1;
        while (b) {
            if (b & 1) res = res * a % MOD;
            a = a * a % MOD;
            b >>= 1;
        }
        return res;
    }
    
    int n, m;
    ll p[9];
    int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
    int dy[8] = {-1, -2, -2, -1, 1, 2, 2, 1};
    
    ll E[MAXN][MAXN];
    bool inboard(int x, int y) {
        return x >= 1 && x <= n && y >= 1 && y <= m;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0);
    
        cin >> n >> m;
        ll sumw = 0;
        int w[9];
        for (int i = 0; i < 8; i++) {
            cin >> w[i];
            sumw += w[i];
        }
        ll inv_sum = qpow(sumw, MOD - 2);
        for (int i = 0; i < 8; i++) {
            p[i] = w[i] * inv_sum % MOD;
        }
    
        // 高斯-赛德尔迭代
        const int iter = 200; // 迭代次数,根据精度调整
        for (int t = 0; t < iter; t++) {
            for (int x = 1; x <= n; x++) {
                for (int y = 1; y <= m; y++) {
                    ll s = 1;
                    for (int k = 0; k < 8; k++) {
                        int nx = x + dx[k], ny = y + dy[k];
                        if (inboard(nx, ny)) {
                            s = (s + p[k] * E[nx][ny]) % MOD;
                        }
                    }
                    E[x][y] = s;
                }
            }
        }
    
        int q;
        cin >> q;
        while (q--) {
            int sx, sy;
            cin >> sx >> sy;
            cout << E[sx][sy] << '\n';
        }
    
        return 0;
    }
    

    样例验证

    对样例1:

    • (2,2)(2,2) 输出 11
    • (1,1)(1,1) 输出 332748119332748119,即 43332748119(mod998244353)\frac{4}{3} \equiv 332748119 \pmod{998244353}

    总结

    本题是典型的马尔可夫链期望步数问题,通过建立线性方程组并利用稀疏性迭代求解,可以在合理时间内得到答案。
    对于更大的数据范围,可能需要更高效的迭代方法或多网格技术加速收敛。

    • 1

    信息

    ID
    3324
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者