一本通OJ-火柴游戏
火柴游戏
题意
我们对于\(n\)堆火柴,每次操作可以拿去\([0,num[i]]\)个火柴,求算先手是否必胜,若必胜,求先手必胜策略,反之输出\('lose'\)。
分析
这是一个\(Nim\)游戏。定义 Nim 和 $=a_{1} \ xor \ a_{2} \ xor \ a_{3}...... \ xor \ a_{n} $。
当且仅当 Nim 和为 \(0\) 时,该状态为必败状态;否则该状态为必胜状态。
必胜策略:
我们首先拿到\(a[i]\)在二进制下在\(Nim\)和最高位的位上为一的\(i\)。而后我们去掉\(a[i] \ xor \ x\)个石子。而后我们输出状态即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 7;
int n, a[N];
int main() {
scanf("%d", &n);
int x = 0;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), x ^= a[i];
if(x==0) return printf("lose"),0;
int id = 0;
for (int i = 1; i <= n; i++) {
if (a[i] >> __lg(x) & 1) {
id = i;
break;
}
}
printf("%d %d\n", a[id] - (a[id] ^ x), id);
for (int i = 1; i <= n; i++) {
printf("%d ", i == id ? a[id] ^ x : a[i]);
}
return 0;
}