一本通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;
}
posted @ 2023-07-25 14:09  Zimo_666  阅读(18)  评论(0编辑  收藏  举报