1 条题解
-
0
自动搬运
来自洛谷,原作者为

kuansoudafahao
**搬运于
2025-08-24 21:22:53,当前版本为作者最后更新于2018-08-11 22:39:29,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
感觉题解的证明都不是很详细啊。。。。。。那本蒟蒻来发一下从网上+自己理解的证明吧。
设为三堆石子的个数,先手为 甲;后手为乙。
必败局势,一般称为奇异局势,显然是一个奇异局势(因为谁面对这种局势,都无法做到游戏给出的条件:每次最少取一个)
讨论局势是必败还是必胜,都是相对于首先面对此局势者来说。因此站在甲的角度来讨论。甲面对必输。
当甲面对,甲每次拿,乙随后也跟着拿,因此甲面对的局势始终是。因此转化为甲最终都会面对,因此甲必输。
因为游戏是两个人交替进行。由此可得,如果局势(a,b,c)是必胜局势,那么甲就有策略,使得拿走某堆中的个物品后,一般地设为。此时就是一个必败的局面。反之,必败的局面可以变为必胜的局面。
更一般地,考虑堆石子的情况。每堆数量为
定理:为奇异局势当且仅当
证明:时显然成立。
当不为时,若 ,显然的最高位为。
则一定存在一个,它在的最高位的值为。(若在的最高位处都为,那么异或运算规则,不可能得到的最高位为)
因此,(因为最高位变为了)
设,则$a_1\oplus a_2 \oplus...\oplus a_{i'}...\oplus a_N=a_1\oplus a_2\oplus ...\oplus a_N \oplus k$ (代入,并由异或的交换律得到)
因此当时,存在移动 (即)使得
若,则不存在合法移动,使得$a_1\oplus a_2 \oplus...\oplus a_{i'}...\oplus a_N=0$。
因为若$a_1\oplus a_2 \oplus...\oplus a_{i'}...\oplus a_N=a_1\oplus a_2 \oplus...\oplus a_{i'}...\oplus a_N=0$,则两边同时异或,可得$a_2\oplus ...a_i\oplus ...\oplus a_N=a_2\oplus ...a_{i'}\oplus ...\oplus a_N$, 继续两边异或(除了共有的),由此可推出。显然这不是合法的移动。
由以上证明得出
-
,一定存在一步特定移动使得;
-
,不存在一步合法移动使得再次为,
-
当时,下一步必然为$a_1\oplus a_2 \oplus...\oplus a_{i'}...\oplus a_N\neq0$,再下一步可以变为$a_1\oplus a_2 \oplus...\oplus a_{i''}...\oplus a_N=0$。
必要性:由为奇异局势(必败局势),考虑甲先乙后。
假设$a_1\oplus a_2 \oplus...\oplus a_i...\oplus a_N\neq0$,那么甲通过移动,可使$a_1\oplus a_2 \oplus...\oplus a_{i'}...\oplus a_N=0$。如此一直下去,每次乙都只能面对的局势。
由于游戏的结束点必然为,因此乙最终将面对。在乙面对的上一步,设为,此时。
但乙最终先面对了,显然是甲胜,这与为奇异局势(必败局势,甲必败)矛盾。
因此必有。
充分性:由 ,由上,乙始终有办法让甲面对的局势始终是。因此甲最终面对的必然是的局势,而就是个奇异局势。
证毕。
理解了奇异局势的判定后,这道题就很好做了。代码也超级简单。
#include <cstdio> int n; int a[500005]; int main() { scanf("%d",&n); int check=0; for(int i=1; i<=n; i++) { scanf("%d",&a[i]); check^=a[i]; } if(!check) { printf("lose\n"); return 0; } for(int i=1; i<=n; i++) { if((check^a[i])<a[i]) { printf("%d %d\n",a[i]-(check^a[i]),i); for(int j=1; j<=n; j++) if(j!=i) printf("%d ",a[j]); else printf("%d ",check^a[i]); break; } } return 0; } -
- 1
信息
- ID
- 247
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者