引子

校赛遇到了一道很经典的$Nim$问题,借此机会严格证明一下。

参考资料

Nim的博弈详解(简单易懂)(一)_nim博弈-CSDN博客

G58 尼姆(Nim)游戏【博弈论】_哔哩哔哩_

Nim游戏

定义

$n$堆物品,每堆有$a_i$个,两个玩家轮流取走任意一堆的任意个物品,但不能不取。

取走最后一个物品的人获胜。

结论

$a_1\bigoplus a_2 \bigoplus \cdots \bigoplus a_n \neq 0$,则先手必胜。

$a_1\bigoplus a_2 \bigoplus \cdots \bigoplus a_n = 0$,则先手必败。

证明

Nim例题

题面

时间限制:C/C++ 1000MS,其他语言 2000MS
内存限制:C/C++ 512MB,其他语言 1024MB

描述

$Alice$和$Bob$在玩游戏。现有三个整数$a,b,c$,确保存在一个三条边分别为$a,b,c$的非退化的三角形。游戏按如下方式进行:玩家轮流地对$a,b,c$中的某个整数进行减法(减去某个正整数)操作。当边$a,b,c$不再能构成一个非退化的三角形,当前玩家就输了。

$Alice$先玩。如果两个玩家都以最优的策略玩,$Alice$能赢吗?

注:退化三角形是指三角形的三个点在一条直线上。

输入描述

第一行为一个整数$T(1\leq T \leq 10^4)$,表示测试用例数。

对于每个测试用例,输入只有一行三个整数$a,b,c(1 \leq a,b,c \leq 10^9)$。确保存在一个非退化的三角形,它的边分别是$a,b,c$。

输出描述

对于每个测试用例,如果$Alice$能赢,输出一行“Win”,否则输出一行“Lose”。

用例输入 1

3
2 2 3
2 3 4
5 3 4

用例输出 1

Win
Lose
Win

解题思路

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef __int128 i128;
typedef long long ll;
typedef double db;

const db PI = acos(-1);
typedef array<ll, 2> PII; // vector<PII> a(n + 1);
const ll inf = 2e18 + 10;
const int mod = 998244353;
const int maxn = 2e5 + 10;
bool multi = 1;

void Solve() {
    ll a, b, c; cin >> a >> b >> c;
    if(((a - 1) ^ (b - 1) ^ (c - 1)) == 0) cout << "Lose\n";
    else cout << "Win\n"; 
}


signed main() {
    // freopen("test.in","r",stdin);  
    // freopen("code.out","w",stdout);    
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    ll T = 1;
    if(multi) cin >> T;
    while(T -- ) {
        Solve();
    }
    return 0;
}