[AcWing 891] Nim游戏

image


点击查看代码
#include<iostream>

using namespace std;

int main()
{
    int n;
    cin >> n;
    int res = 0;
    while (n --) {
        int x;
        scanf("%d", &x);
        res ^= x;
    }
    if (res)    puts("Yes");
    else    puts("No");
    return 0;
}

  1. 先手必胜状态和先手必败状态
    ① 先手必胜状态:可以走到某一个必败状态;
    ② 先手必败状态:走不到任何一个必败状态;
  2. 结论:假设 n 堆石子,石子的数目分别是 a1,a2,,an ,如果 a1a2an0 ,则先手必胜,否则,先手必败
    000=0 ,说明没有石子可拿;
    ② 如果 a1a2an=x0 ,那么玩家必然可以通过拿走某一堆里面的若干个石子,使得异或值变为 0
    证明:不妨设 x 的二进制表示中,最高位 1x 的第 k 位,那么必然存在一个 aiai 的第 k 位为 1 (反证法:如果 a1,a2,,an 的第 k 位都为 0,则 x 的第 k 位也必然为 0,与最高位 1x 的第 k 位矛盾),aix<ai,那么从第 i 堆石子中拿走 (aiaix) 个石子,第 i 堆石子还剩 ai(aiaix)=aix ,此时 a1a2an=xx=0
    ③ 如果 a1a2an=0,那么无论玩家怎么拿,最终的异或值都不为 0
    反证法:假设玩家从第 i 堆石子拿走若干个,异或值为 0,不妨设第 i 堆还剩下 ai 个,0ai<aia1a2aian=0,那么 (a1a2aian)(a1a2aian)=0(aiai)=0,推出 aiai=0ai=ai,与 ai<ai 矛盾,证明完毕
    ④ 基于上述结论,当先手遇到的是 a1a2an=x0,必然可以通过拿走某一堆里面的若干个石子,使得异或值变为 0,而后手无论怎么拿,最终的异或值都不为 0,不断重复这个过程,后手必然会遇到 000=0 这一失败的局面,而当先手遇到的是 a1a2an=0 的局面时,都会给后手创造 a1a2an=x0 的局面,先手必败
posted @   wKingYu  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
欢迎阅读『[AcWing 891] Nim游戏』
点击右上角即可分享
微信分享提示