Nim博弈原理与证明

简介

Nim博弈的定义是:

给定 \(n\) 堆物品,第 \(i\) 堆物品有 \(A_i\) 个,两人轮流取,每次可以任选一堆取走任意多个物品,可以取光但不能不取,最后把物品全部取完者胜利

判断先手是否有必胜策略

推理

证明:当 \(A_1\oplus A_2\oplus\cdots\oplus A_n\not = 0\) 时先手必胜

  • 所有物品被取完是一个必败局面,此时显然有 \(A_1\oplus A_2\oplus\cdots\oplus A_n = 0\)

  • \(A_1\oplus A_2\oplus\cdots\oplus A_n=x\not = 0\) ,设 \(x\) 的二进制表示下最高的 \(1\) 在第 \(k\) 位,那么至少存在一堆物品 \(A_i\) ,它的第 \(k\) 位是 \(1\) 。而由于 \(A_i\oplus x\) 的第 \(k\) 位为 \(0\) ,更高位与 \(A_i\) 相同,所以 \(A_i\oplus x<A_i\) ,所以我们只需要从 \(A_i\) 中取走若干物品使其变为 \(A_i\oplus x\) ,此时物品数异或和为 \(x\oplus A_i\oplus A_i\oplus x=0\)

  • \(A_1\oplus A_2\oplus\cdots\oplus A_n=0\) ,那么无论如何取,得到的异或结果都不为 \(0\) ,用反证法证明,如果 \(A_i\) 被取成了 \(A_i^{'}\) 后异或和为 \(0\) ,那么有:

    \[A_1\oplus A_2\oplus\cdots\oplus A_i^{'}\oplus \cdots \oplus A_n=0\\ \Rightarrow A_1\oplus A_1\oplus\cdots\oplus A_i\oplus A_i^{'}\oplus\cdots\oplus A_n\oplus A_n=0\\ \Rightarrow A_i\oplus A_i^{'}=0,A_i=A_i^{'} \]

    与不能不取物品矛盾

综上,由归纳法可知,命题成立

代码

POJ 2234

#include<iostream>
#include<cstdio>
using namespace std;

int main()
{
    int m;
    while(cin >> m) {
        int x, res = 0;
        for(int i = 1; i <= m; i++) {
            scanf("%d", &x);
            res = res ^ x;
        }
        printf("%s\n", res ? "Yes" : "No");   
    }
    return 0;
}
posted @ 2022-02-15 17:43  f(k(t))  阅读(181)  评论(0编辑  收藏  举报