「AcWing学习记录」博弈论

AcWing 891. Nim游戏

原题链接

定理: Nim博弈先手必胜,当且仅当

\[a_1\wedge a_2\wedge\cdots \wedge a_n != 0 \]

问题1:当没有石子可拿的时候异或值为0,即

\[0\wedge 0\wedge\cdots \wedge 0 = 0 \]

问题2:当面临异或值不为0的局面时,一定可以从某堆石子中拿走一部分使剩下的石子异或值为0。

\[a_1\wedge a_2\wedge\cdots \wedge a_n = x != 0 \]

假设x的二进制表示中最高一位1在第k位,那么\(a_1\)~\(a_n\)中必然存在一个数\(a_i\)的第k位是1,且 \(a_i\wedge x < a_i\)
又因为

\[a_i - (a_i - (a_i\wedge x)) = a_i\wedge x \]

\[a_1\wedge a_2\wedge\cdots \wedge a_i\wedge x\wedge a_{i+1}\wedge\cdots \wedge a_n = x\wedge x = 0 \]

所以当从第i堆石子中拿走\(a_i - (a_i\wedge x)\)个石子时,可以使剩下的石子异或值为0。
问题3:当面临异或值为0的局面时,如果拿走一部分石子,一定会使剩下的石子异或值不为0。
利用反证法证明,假设当\(a_1\wedge a_2\wedge\cdots \wedge a_n = 0\)时,拿走一部分石子,剩下的石子异或值仍为0。
\(a_i\)为第i堆石子原本的石子数,\(a_i'\)为拿走一部分石子后第i堆石子的石子数,则有

\[a_1\wedge a_2\wedge\cdots \wedge a_i\wedge a_{i+1}\wedge\cdots \wedge a_n = 0 \]

\[a_1\wedge a_2\wedge\cdots \wedge a_i'\wedge a_{i+1}\wedge\cdots \wedge a_n = 0 \]

将上下等式左右两边异或起来,有\(a_i\wedge a_i' = 0\),即 \(a_i = a_i'\),说明拿走前与拿走后的石子数相等,这与假设不相符,原命题成立。

#include<iostream>
#include<algorithm>

using namespace std;

int main()
{
    int n;
    int res = 0;

    scanf("%d", &n);
    while(n--)
    {
        int x;
        scanf("%d", &x);
        res ^= x;
    }

    if(res) puts("Yes");
    else puts("No");

    return 0;
}

AcWing 892. 台阶-Nim游戏

原题链接


AcWing 893. 集合-Nim游戏

原题链接


AcWing 894. 拆分-Nim游戏

原题链接


posted @ 2023-02-12 17:32  恺雯  阅读(15)  评论(0编辑  收藏  举报