首先我们看例题:P2197 nim游戏

题目描述

甲,乙两个人玩Nim取石子游戏。

nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取完,不能不取。每次只能从一堆里取。最后没石子可取的人就输了。假如甲是先手,且告诉你这n堆石子的数量,他想知道是否存在先手必胜的策略。

输入输出格式

输入格式:

第一行一个整数T<=10,表示有T组数据

接下来每两行是一组数据,第一行一个整数n,表示有n堆石子,n<=10000;

第二行有n个数,表示每一堆石子的数量

输出格式:

共T行,如果对于这组数据存在先手必胜策略则输出"Yes",否则输出"No",不包含引号,每个单词一行。

输入输出样例

输入样例#1:

2
2
1 1
2
1 0
输出样例#1:

No
Yes

讲解:
本题就是最最经典的nim游戏了。nim游戏过程中面临的状态叫做局面,第一个行动的为先手,第二个行动的为后手。考虑两人无比聪明,则必败局面仅当该局面所能到达的局面均为必败局面时出现,而必胜局面仅当后续局面存在至少1个必胜局面时出现,显然nim游戏中1为必胜局面(因为拿走1就赢了)。显然,nim游戏是不存在平局的,只有先手必赢或先手必输两种情况。

定理:设各堆为a1、a2…an,则nim游戏先手必赢仅当a1 Xor a2 Xor…Xor an≠0.

证明:

  首先,当石子均被取完时,则a数组都为0,存在a1 Xor a2 Xor…Xor an=0,因为每次取都会使石子数减少,当前局面若a1 Xor a2 Xor…Xor an≠0,我们只要保证能在取走一些石子后使得a1 Xor a2 Xor…Xor an=0,则必然保证自己能取走最后一个石子获得胜利。

  等价于证明:

  (1)当a1 Xor a2 Xor…Xor an≠0时,存在某种取法使得剩下的石子xor和为0。

  (2)当a1 Xor a2 Xor…Xor an=0时,不存在取法使得剩下的石子xor和为0。(即取走一些石子后必定Xor和不为0)

  首先证明(1),对于任何一个局面a1 Xor a2 Xor…Xor an=x≠0,设x的二进制最高位的1在第k位,则至少存在一堆石子ai的二进制第k位是1(因为我们是Xor运算,某一位上的1不会凭空出现)且ai≥x。由Xor运算法则知:x Xor ai<ai,(因为至少会使第k为上的1变为0)。于是我们从ai这堆里取走一些石子,使得ai堆剩下的石子数变为ai Xor x,此时再对剩下的各堆进行上述运算:a1 Xor a2 Xor…ai Xor x…Xor an=x Xor x=0,此时Xor和为0。 于是得证(1)。

  再来证明(2),对于任何一个局面a1 Xor a2 Xor…Xor ai Xor…an=0,我们反证:假设取走ai堆中的一些石子使ai变为了x,使得a1 Xor a2 Xor…Xor x Xor…an≠0,则显然是不可能的,因为开始Xor和就为0再由Xor运算的性质当ai变为x后若Xor和为0,当且仅当ai=x时成立。而nim游戏中不能不取,所以若当前局面Xor和为0,则必然会使下一局面Xor和不为0。于是(2)得证。

结论:nim游戏只要满足先手的Xor和不为0,则先手必赢,否则先手必输。

代码:

#include<bits/stdc++.h>
#define il inline
#define ll long long
using namespace std;
il ll gi()
{
ll a=;char x=getchar();bool f=;
while((x<''||x>'')&&x!='-')x=getchar();
if(x=='-')x=getchar(),f=;
while(x>=''&&x<='')a=a*+x-,x=getchar();
return f?-a:a;
}
ll t,n,a[];
int main()
{
t=gi();
while(t--){
n=gi();ll x=;
for(int i=;i<=n;i++)a[i]=gi(),x^=a[i];
if(x)puts("Yes");
else puts("No");
}
return ;
}

浅析Nim游戏(洛谷P2197)的更多相关文章

  1. 洛谷 P2197 nim游戏

    洛谷 P2197 nim游戏 题目描述 甲,乙两个人玩Nim取石子游戏. nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取 ...

  2. 洛谷 P2197 【模板】nim游戏 解题报告

    P2197 [模板]nim游戏 题目描述 甲,乙两个人玩Nim取石子游戏. nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以 ...

  3. 洛谷P2197 nim游戏(Nim游戏)

    题目描述 甲,乙两个人玩Nim取石子游戏. nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取完,不能不取.每次只能从一堆里 ...

  4. [洛谷P2197]nim游戏

    题目大意:Nim游戏.地上有n堆石子,每人每次可从任意一堆石子里取出任意多石子,不能不取,且每次只能从一堆里取.没石子可取的人输.问是否存在先手必胜的策略. 题解:Nim游戏有一个定理,就是当所有棋子 ...

  5. P4554 小明的游戏 (洛谷) 双端队列BFS

    最近没有更新博客,全是因为英语,英语太难了QWQ 洛谷春令营的作业我也不会(我是弱鸡),随机跳了2个题,难度不高,还是讲讲吧,学学新算法也好(可以拿来水博客) 第一题就是这个小明的游戏 小明最近喜欢玩 ...

  6. NOIP2012 Day1 T2国王游戏 洛谷P1080

    第一篇博客啊…… 由于我太弱了,还要去补不全的知识点准备参加人生第一次NOIp,所以第一篇博客就简短一点好了(偷懒就直说吧……) 洛谷P1080传送门 题意概括: 有N对数ai和bi,以及两个数a0和 ...

  7. 洛谷P2197 nim游戏模板

    Code: #include<iostream> using namespace std; int main(){ int t; cin>>t; while(t--){ int ...

  8. AC日记——欧几里得的游戏 洛谷 P1290

    题目描述 欧几里德的两个后代Stan和Ollie正在玩一种数字游戏,这个游戏是他们的祖先欧几里德发明的.给定两个正整数M和N,从Stan开始,从其中较大的一个数,减去较小的数的正整数倍,当然,得到的数 ...

  9. 矩阵取数游戏洛谷p1005

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...

随机推荐

  1. 成都Uber优步司机奖励政策(3月31日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  2. 成都Uber优步司机奖励政策(1月16日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  3. P1803 凌乱的yyy

    P1803 凌乱的yyy 题目背景 快noip了,yyy很紧张! 题目描述 现在各大oj上有n个比赛,每个比赛的开始.结束的时间点是知道的. yyy认为,参加越多的比赛,noip就能考的越好(假的) ...

  4. Updating Homebrew... 长时间不动解决方法

    确保你已安装Homebrew 依次输入下面的命令(注意:不要管重置部分的命令,这里原作者贴出来.我也贴出来是以防需要重置的时候有参考操作命令) 替换brew.git: cd "$(brew ...

  5. golang 仿python pack/unpack

    写得不完善也不完美 尤其是高低位转换那(go和c 二进制高地位相反 需要转换,还有go int转[]byte长度是4位),希望牛人看后指导一下 项目需要通过socket调取 客户端是go ,服务器端是 ...

  6. atomic是绝对的线程安全么?为什么?如果不是,那应该如何实现?

    atomic不是绝对的线程安全.atomic的本意是指属性的存取方法是线程安全的,并不保证整个对象是线程安全的 @property (atomic, assign) int intA; //线程A f ...

  7. 第五篇 Flask组件之SQLAchemy及Flask-SQLAlchemy插件/Flask-Script/Flask-migrate/pipreqs模块

    SQLAlchemy组件 一. 介绍 SQLAlchemy是一个基于Python实现的ORM框架.该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之便是:将类和对象转换成SQL,然 ...

  8. Python字符串格式化符号及转义字符含义(非常全!!!)

    字符串格式化符号含义 符号 说明 %c 格式化字符及其 ASCII 码 %s 格式化字符串 %d 格式化整数 %o 格式化无符号八进制数 %x 格式化无符号十六进制数 %X 格式化无符号十六进制数(大 ...

  9. node事件循环

    Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发. Node.j ...

  10. [Clr via C#读书笔记]Cp3共享程序集和强命名程

    Cp3共享程序集和强命名程序集 私有方式部署+全局方式部署:弱命名程序集+强命名程序集 强命名程序集使用发布者的公钥私钥进行签名,唯一标识发布者. 共享dll被全部复制到System32中 强命名程序 ...