• 【bzoj1022】小约翰的游戏John


    Portal -->bzoj1022

    Solution

    ​   这题其实是裸的反Nim,这里主要是为了写反Nim游戏的证明

    ​   首先给出反Nim(anti-nim)的定义和结论:

    【定义】桌子上有 N 堆石子,游戏者轮流取石子; 每次只能从一堆中取出任意数目的石子,但不能不取;取走最后一个石子者败

    【结论】先手必胜当且仅当满足下面两个条件中的一个

    ​   (1)所有堆的石子数都为(1)且游戏的(sg)值为(0)

    ​   (2)有些堆的石子数大于(1)且游戏的(sg)值不为(0)

    ​ ​  

    ​   然后我们来证明anti-nim游戏的结论,可以分成两种情况讨论(以下内容摘自论文):

    1、每堆只有(1)个石子:

    ​   那么显然先手必胜当且仅当石子堆数(n)为偶数

    2、其他情况:

    ​​   (1)当游戏的(sg)值不为(0)时:若还有至少两堆石子的数目大于$ 1$,则先手将 (sg)值变为 (0)即可;若只有一堆石子数大于(1),则先手总可以将状态变为有奇数个(1)(可以把大于(1)的那堆直接取完或者取剩(1)个),所以,当(sg)不为(0)时先手必胜

    ​​   (2)当游戏的(sg)值为(0)时:至少有两堆石子的数目大于 (1),则先手决策完之后,必定至少有一堆的石子数大于 (1),且(sg)值(当前游戏局面的)不为(0),由上段的论证我们可以发现,此时,无论先手如何决策,都只会将游戏带入先手必胜局,所以先手必败

    ​  

    ​   代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,T,ans,cnt;
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	int x;
    	scanf("%d",&T);
    	for (int o=1;o<=T;++o){
    		ans=0; cnt=0;
    		scanf("%d",&n);
    		for (int i=1;i<=n;++i){
    			scanf("%d",&x),ans^=x;
    			if (x>1) ++cnt;
    		}
    		if (cnt==0) printf(n%2?"Brother
    ":"John
    ");
    		else printf(ans?"John
    ":"Brother
    ");
    	}
    }
    
  • 相关阅读:
    苦逼也聊模式--(0)--开篇
    发现无力吐槽
    JS函数调用
    初步使用nodejs(一)
    测试一下
    达摩流浪者
    Revit:二开使用Sqlite保存本地数据,并配合EF6等ORM框架
    Revity:查找并修改类型参数和实例参数
    复习一下UML
    Revit:ElementFilter过滤器基类
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9425543.html
Copyright © 2020-2023  润新知