题解 : Luogu P2197 【模板】nim 游戏

题目链接:link

结论

如果 a1a2...an0 ,则先手必胜

证明

  1. 操作到最后时,每堆石子数都是0, 00...0=0

  2. 如果a1a2...an=x0,那么肯定可以通过从某一堆中拿走若干颗石子后,将异或结果变成0

    证明:我们先假设 x的最高一位的1在第k位,
    那么在 a1,a2,...,an 中,一定存在一个 ai ,它的第k位为1,
    aix一定是小于ai的,那么在ai中取ai(aix)颗石子,就可以得到a1a2...an=0,
    因为ai中取了ai(aix)颗石子后,就还剩ai(ai(aix))颗石子,也就是aix

  3. 如果a1a2...an=0,那么无论怎么拿,最终的异或结果一定不为0

    反证法:假设从第i堆石子中拿了若干个,结果仍然为0
    先设第i堆拿完后还剩ai颗石子,由于不能不拿,所以0<ai<ai,而且a1a2...ai...an=0,
    那么(a1a2...ai...an)(a1a2...ai...an)=0,
    aiai=0,也就是ai=ai,和0<ai<ai矛盾

那么如果a1a2...an=x0,那么先手总可以从某堆拿走若干颗石子,使得a1a2...an=0,那么最终后手一定没有石子可以拿,则先手必胜
否则,无论先手怎么拿,都会使得a1a2...an0,那么此时后手就变成了先手,所以最初的先手必败

代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int k,n,ans,x;
    scanf("%d",&k);
    while (k--)
    {
        ans=0;
        scanf("%d",&n);
        while (n--)
        {
            scanf("%d",&x);
            ans^=x;
        }
        if (ans) puts("Yes");
        else puts("No");
    }
    return 0;
}
posted @   懵逼自动机  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示