1 条题解
-
0
题意简述
给定两个长度为 的二进制串 和 。每次操作可以选择区间 ,然后对所有 同时将 替换为 (下标从 开始)。可以执行任意多次操作,问能否将 变成 。
核心性质
操作的本质是把 的某个前缀(长度为 )的每一位异或到 的对应子区间 上。
不难观察到以下事实:- 如果 全为 ,则任何操作都无法产生 ,因此只有当 也全为 时才有可能。
- 如果 中有 ,则可以通过一系列操作在 第一个 的位置及其右侧 的任意位置生成或消除 ,但无法在第一个 的左侧产生 。换言之,第一个 的位置只会向右移动,不会向左移动。
因此,一个充要条件是:
- 若 中存在 ,设 为 中第一个 的位置(若不存在则游戏不可能有趣), 为 中第一个 的位置。那么必须满足 。
- 若 中全为 ,则只有当 也全为 时游戏才可能有趣。
算法实现
遍历字符串找到两个串中第一个
'1'的位置(若没有则记为极大值),然后根据上述条件判断即可。时间复杂度 ,总复杂度 ,足够快。
参考代码
#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
- 上传者