2025.02.25 CW 模拟赛 D. 博弈论
D. 博弈论
给我绕昏了.
思路
考虑什么时候会是 Draw
. 可以发现若 Alice 和 Bob 手中的数相等, 那么异或和就为 0, 也就是整个序列的异或和为 0. 接下来考虑异或和不为 0 的情况.
不妨设序列异或和为 \(s\). 我们对于每一位考虑, 如果这一位上是 0, 那么在这一位上, Alice 和 Bob 即为平局 \((\)因为异或和为 0\()\); 如果这位是 1, 那么就可以决出胜负. 所以我们要考虑的位便成了 \(s\) 的最高位.
我们分 \(n\) 为奇数和偶数分别讨论:
-
\(n\) 为偶数, 先手必胜.
因为我们有奇数个 1, 那么在偶数位 / 奇数位上一定存在奇数个 1. 同时先手又可以任意控制后手选的位的奇偶性, 所以其一定可以选到奇数个 1, 先手必胜. \((\)举个例子, 序列为
10101011
, 那么在奇数位上我们有奇数个 1. 如果先手选择第 1 个位置, 那么后手就只能选择第 2 / n 个位置, 这样一来, 相当于后手一直在选偶数位, 先手一直在选奇数位, 其就必胜\()\) -
\(n\) 为奇数.
如果序列两端都是 0, 无论先手选哪边都会转化为「\(n\) 为偶数, 有奇数个 1」的情况, 先手必败.
否则先手必然会取两端中的一个 1, 然后无论后手取哪个, 先手就必须跟着取, 不然就会转化为必败态.
所以我们可以先将相同的前后缀的消掉, 然后剩下的位置必须是「相邻的奇偶数位相同」先手才有可能胜 \((\)例如
001100...
\()\), 否则后手必胜.另外, 若 1 的个数不为 4 的倍数, 先手和后手会将数字全部取完, 由于先手每次会与后手选择相同的数, 于是先手会选奇数个 1, 再加上最开始的一个 1, 总共偶数个 1, 输了. 所以先手胜的条件还有「1 的个数是 4 的倍数」.
总时间复杂度 \(\mathcal{O}(\sum n)\).
代码
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
using namespace std;
constexpr int N = 1e5 + 10;
int n, a[N], s, cnt;
bool check(int l, int r) {
for (; a[l] == a[r]; ++l, --r);
for (int i = l; i <= r; i += 2)
if (a[i] ^ a[i + 1]) return false;
return true;
}
void init() {
cin >> n, s = cnt = 0;
for (int i = 1; i <= n; ++i) cin >> a[i], s ^= a[i];
int w = getbit(s);
for (int i = 1; i <= n; ++i) a[i] = a[i] >> w & 1, cnt += a[i];
}
void calculate() {
if (!s) return puts("Draw"), void();
if (!(n & 1)) return puts("Alice"), void();
if (!(a[1] + a[n]) or cnt % 4 ^ 1) return puts("Bob"), void();
int f = 0;
if (a[1]) f or_eq check(2, n);
if (a[n]) f or_eq check(1, n - 1);
puts(f ? "Alice" : "Bob");
}
void solve() {
cin.tie(nullptr);
int T; cin >> T;
while (T--) {
init();
calculate();
}
}
int main() {
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理