1 条题解

  • 0
    @ 2026-5-5 15:22:00

    题意简述

    给定两个长度为 nn 的二进制串 sstt。每次操作可以选择区间 [l,r][l, r],然后对所有 i[l,r]i \in [l, r] 同时将 sis_i 替换为 sisil+1s_i \oplus s_{i-l+1}(下标从 11 开始)。可以执行任意多次操作,问能否将 ss 变成 tt

    核心性质

    操作的本质是把 ss 的某个前缀(长度为 rl+1r-l+1)的每一位异或到 ss 的对应子区间 [l,r][l, r] 上。
    不难观察到以下事实:

    1. 如果 ss 全为 00,则任何操作都无法产生 11,因此只有当 tt 也全为 00 时才有可能。
    2. 如果 ss 中有 11,则可以通过一系列操作在 第一个 11 的位置及其右侧 的任意位置生成或消除 11,但无法在第一个 11 的左侧产生 11。换言之,第一个 11 的位置只会向右移动,不会向左移动

    因此,一个充要条件是:

    • tt 中存在 11,设 psp_sss 中第一个 11 的位置(若不存在则游戏不可能有趣),ptp_ttt 中第一个 11 的位置。那么必须满足 psptp_s \le p_t
    • tt 中全为 00,则只有当 ss 也全为 00 时游戏才可能有趣。

    算法实现

    遍历字符串找到两个串中第一个 '1' 的位置(若没有则记为极大值),然后根据上述条件判断即可。

    时间复杂度 O(n)O(n),总复杂度 O(n)2×105O(\sum n) \le 2\times 10^5,足够快。

    参考代码

    #include <bits/stdc++.h>
    using namespace std;
    
    void solve() {
        int n;
        cin >> n;
        string s, t;
        cin >> s >> t;
    
        int ps = -1, pt = -1;
        for (int i = 0; i < n; ++i) {
            if (s[i] == '1' && ps == -1) ps = i;
            if (t[i] == '1' && pt == -1) pt = i;
        }
    
        bool ok = false;
        if (pt == -1) {
            // t 全 0,则 s 必须全 0
            ok = (ps == -1);
        } else {
            // t 有 1,则 s 必须有 1 且第一个 1 不能比 t 的第一个 1 晚
            ok = (ps != -1 && ps <= pt);
        }
    
        cout << (ok ? "YES" : "NO") << "\n";
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int q;
        cin >> q;
        while (q--) solve();
        return 0;
    }
    
    • 1

    信息

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