1 条题解

  • 0
    @ 2026-4-15 16:15:35

    1952E - 扫线 详细题解(官方标程版)

    题意规范化翻译

    有一个一维扫雷游戏,只有一行格子。 给定长度为 nn 的数组 aa,满足 0ai20\le a_i\le 2。 每个 aia_i 表示ii 格左右相邻格子的地雷总数不含自身)。

    xi{0,1}x_i\in\{0,1\} 表示第 ii 格是否有地雷:

    • xi=1x_i=1:有地雷
    • xi=0x_i=0:没有地雷

    则对每个 ii 必须满足:

    ai=xi1+xi+1a_i = x_{i-1} + x_{i+1}

    边界约定x0=0, xn+1=0x_0 = 0,\ x_{n+1} = 0(最左、最右外都没有地雷)。

    求合法地雷布局 xx方案数,答案对 2024040120240401 取模。 (标程指出:答案只会是 0,1,20,1,2,取模无实际意义。)


    核心结论(标程原话)

    整个数组 x2,,xnx_2,\dots,x_n x1x_1 唯一确定x1x_1 只有 0011 两种可能,因此总方案数 2\le 2


    严格推导(标程逻辑)

    由约束:

    ai=xi1+xi+1a_i = x_{i-1} + x_{i+1}

    移项得到递推式

    xi+1=aixi1x_{i+1} = a_i - x_{i-1}

    第一步:由 a1a_1 直接得 x2x_2

    i=1i=1 时:

    a1=x0+x2=x2a_1 = x_0 + x_2 = x_2

    所以:

    x2=a1x_2 = a_1

    第二步:递推推出全部 xx

    i=2,3,,n1i=2,3,\dots,n-1

    xi+1=aixi1x_{i+1} = a_i - x_{i-1}

    每一步必须满足:

    xi{0,1}x_i\in\{0,1\}

    否则该 x1x_1 对应的方案非法。

    第三步:最终校验(关键)

    i=ni=n 时:

    an=xn1+xn+1=xn1a_n = x_{n-1} + x_{n+1} = x_{n-1}

    所以必须满足:

    an=xn1a_n = x_{n-1}

    不满足则方案非法。


    算法流程(标准 O(n)O(n)

    1. 枚举 x1{0,1}x_1\in\{0,1\}
    2. 对每个 x1x_1
      • x2=a1x_2 = a_1
      • x2{0,1}x_2\notin\{0,1\},非法
      • 递推 x3xnx_3\sim x_nxi+1=aixi1x_{i+1}=a_i-x_{i-1}
      • 若任意 xi{0,1}x_i\notin\{0,1\},非法
      • 最后检查 an=xn1a_n = x_{n-1}
    3. 统计合法的 x1x_1 数量即为答案。

    特殊情况:n=1n=1

    此时:

    a1=x0+x2=0a_1 = x_0 + x_2 = 0

    只有 a1=0a_1=0 时有 11 种方案,否则 00


    标程风格可AC代码(极简、无冗余)

    #include <iostream>
    #include <vector>
    using namespace std;
    
    const int MOD = 20240401;
    
    int test(int n, vector<int>& a, int x1) {
        vector<int> x(n + 2, 0);
        x[1] = x1;
        x[2] = a[1];
        if (x[2] < 0 || x[2] > 1) return 0;
    
        for (int i = 2; i <= n - 1; ++i) {
            x[i+1] = a[i] - x[i-1];
            if (x[i+1] < 0 || x[i+1] > 1)
                return 0;
        }
    
        return (a[n] == x[n-1]) ? 1 : 0;
    }
    
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        int n; cin >> n;
        vector<int> a(n+1);
        for (int i=1; i<=n; ++i) cin >> a[i];
    
        if (n == 1) {
            cout << (a[1] == 0) << endl;
            return 0;
        }
    
        int ans = test(n,a,0) + test(n,a,1);
        cout << ans % MOD << endl;
    }
    

    复杂度

    • 时间:O(n)O(n)
    • 空间:O(n)O(n)(可优化到 O(1)O(1),标程常用)

    答案为什么最多是 2?

    因为只有两个可能:

    x1=0x1=1x_1 = 0 \quad \text{或} \quad x_1 = 1

    每个唯一确定整个布局,最多两个合法。

    • 1

    信息

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