[题解] AtCoder ARC225 B. Independent Nim

[题解] AtCoder ARC225 B. Independent Nim

TAG: 博弈论,构造,思维,AtCoder
题目链接: AtCoder ARC225 B - Independent Nim

题目大意

给定一个只含 01 的序列。Alice 与 Bob 轮流操作,每次必须选择至少一个值为 1 的位置并将其改成 0,但同一次选择的位置不能相邻。无法操作的人失败,Alice 先手,判断谁有必胜策略。

拿到题目后如何思考

1. 先观察最小局面

先只考虑一段连续的 1

  • 1:先手可以直接删掉,先手胜;
  • 11:由于两个位置相邻,一次只能删掉一个,局面变成 1,对手再删掉最后一个,因此先手败;
  • 111:先手删掉最左端或最右端,便可以给对手留下 11,因此先手胜。

这里第一次出现了真正特殊的结构:11

单独的一对 11 不能在一次操作中被全部删掉。无论当前玩家删左边还是右边,都一定会留下一个孤立的 1 给对手。

2. 0 把序列分成若干连续段,但不能直接做 Nim 异或

原序列中的 0 永远不会变回 1,所以它们把所有 1 分成若干个极长连续段。

但是,一次操作可以同时在多个连续段中选择位置。因此这些连续段并不是普通意义下“每次只能选择一个子游戏操作”的 Nim 游戏,不能直接计算每段的 SG 值再异或。

真正应该关注的是:能否用一次操作,把整个局面同时整理成一种后手必胜的标准形。

3. 猜测标准形:所有连续段都恰好是 11

由最小局面可以猜测:

当且仅当每个极长连续 1 段的长度都等于 2 时,当前局面是后手必胜态。

也就是说,形如下面的局面都是后手必胜态:

11
11011
11011011

中间可以有任意多个原本就存在的 0,关键只在于每段连续 1 的长度必须是 2

接下来分别证明标准形不能走到标准形,以及任意非标准形都能一步走到标准形。

为什么若干个独立的 11 不影响先手必胜性质

假设当前所有连续段都是 11

在一对 11 中,两个位置相邻,所以一次操作最多选择其中一个。又因为一次操作至少要选择一个位置,所以至少有一对 11 会被碰到,并在操作后变成单独的 1

因此,从“全部由 11 组成”的局面出发,无论怎样操作,都不可能再次得到“全部由 11 组成”的局面。

这也说明一对独立的 11 是一种中性结构:

  • 如果原局面已经全部由若干对 11 组成,再加入一对独立的 11,仍然是后手必胜;
  • 如果原局面还存在其他非标准连续段,再加入一对 11,也不会消除那个可以控制胜负的非标准段。

所以判断胜负时,可以把已经独立出来的每一对 11 留在原地,不需要主动处理它们。

谁拿到“可支配的 1”,谁就能控制胜负

现在考虑某个长度不等于 2 的连续 1 段。目标是在一次操作后,让它剩下的每个连续段都恰好为 11

下面的构造中:

  • 1 表示这个位置保留;
  • 0 表示选择这个原本为 1 的位置,并在本次操作中将其删除。

按照连续段长度除以 3 的余数构造:

  • 长度为 \( 3k \):构造成 (110) 重复 \( k \) 次;
  • 长度为 \( 3k+1 \):构造成 0 后接 (110) 重复 \( k \) 次;
  • 长度为 \( 3k+2 \):构造成 (110) 重复 \( k \) 次,最后接 11

例如:

1       -> 0
111     -> 110
1111    -> 0110
11111   -> 11011
111111  -> 110110
1111111 -> 0110110

构造后的所有 0 之间都隔着两个 1,所以本次要删除的位置两两不相邻,操作一定合法;留下来的每个连续 1 段又都恰好是 11

长度为 2 时不需要做任何事,直接保留原来的 11 即可。对于其他长度,构造中至少会删除一个位置。

不同极长连续段之间原本就隔着 0,所以可以同时对所有非标准连续段执行上述构造。把各段中要删除的位置合并到同一次操作里,它们仍然不会相邻。

这样,任意不是标准形的局面,都可以一步变成全部由独立 11 组成的标准形。

这里所谓“谁有 1,谁就能控制胜负”,更准确地说是:

谁拿到至少一个没有被固定在标准 11 中的可支配 1,谁就能利用它完成上述整理,把后手必胜的标准形交给对方。

反过来,如果当前只有若干对 11,当前玩家无论如何都必须拆开至少一对,制造出可支配的单独 1。于是对手又能把局面整理回标准形。

必胜态与必败态证明

令标准形表示“每个极长连续 1 段的长度都为 2”。

标准形是必败态

任意合法操作都至少触碰一对 11,并且在这对 11 中最多删除一个位置,因此操作后一定会出现长度为 1 的连续段。也就是说,标准形的任何后继状态都不是标准形。

非标准形是必胜态

对每个长度不为 2 的连续段,使用上面的周期构造删除若干个互不相邻的位置;长度为 2 的连续段保持不动。一次操作后,整个序列中的连续 1 段都会变成 11,即走到标准形。

因此满足博弈论中必败态的两个条件:

  • 必败态的任意后继都是必胜态;
  • 任意必胜态都至少存在一种走向必败态的操作。

最终结论为:

  • 所有极长连续 1 段的长度都为 2,Bob 获胜;
  • 只要存在一个连续段的长度不为 2,Alice 获胜。

0 序列中没有任何连续 1 段,也满足“所有连续段长度均为 2”,此时 Alice 无法进行第一次操作,仍然是 Bob 获胜。

复杂度

只需从左到右扫描序列并统计每个极长连续 1 段的长度。

  • 时间复杂度:\( O(N) \),每个位置只访问一次;
  • 空间复杂度:\( O(1) \),只维护当前连续段长度和答案标记。

代码前说明

  • cnt:当前尚未结束的极长连续 1 段长度;
  • f:当前是否仍满足“已经检查过的每段长度都为 2”;
  • 读到 0:说明一段连续 1 结束,检查 cnt 是否为 02,再清空;
  • 扫描结束:如果序列以 1 结尾,还要单独检查最后一段;
  • f=true 对应后手必胜态,输出 Bob,否则输出 Alice

参考代码

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
void solve(){
	int n;cin>>n;
	bool f=1;
	int cnt=0;
	int x;
	for(int i=1;i<=n;i++){
		cin>>x;
		if(x==1){
			cnt++;
		}else{
			if(cnt!=2&&cnt!=0) f=0;
			cnt=0;
		}
	}
	if(x!=0&&cnt!=2) f=0;
	if(f) cout<<"Bob"<<endl;
	else cout<<"Alice"<<endl;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t=1;cin>>t;
    while(t--) solve();
    return 0;
}
posted @ 2026-07-20 19:54  艾拉别哭  阅读(20)  评论(0)    收藏  举报