浅析Nim游戏(洛谷P2197)
首先我们看例题:P2197 nim游戏
题目描述
甲,乙两个人玩Nim取石子游戏。
nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取完,不能不取。每次只能从一堆里取。最后没石子可取的人就输了。假如甲是先手,且告诉你这n堆石子的数量,他想知道是否存在先手必胜的策略。
输入输出格式
输入格式:
第一行一个整数T<=10,表示有T组数据
接下来每两行是一组数据,第一行一个整数n,表示有n堆石子,n<=10000;
第二行有n个数,表示每一堆石子的数量
输出格式:
共T行,如果对于这组数据存在先手必胜策略则输出"Yes",否则输出"No",不包含引号,每个单词一行。
输入输出样例
2
2
1 1
2
1 0
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)的更多相关文章
- 洛谷 P2197 nim游戏
洛谷 P2197 nim游戏 题目描述 甲,乙两个人玩Nim取石子游戏. nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取 ...
- 洛谷 P2197 【模板】nim游戏 解题报告
P2197 [模板]nim游戏 题目描述 甲,乙两个人玩Nim取石子游戏. nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以 ...
- 洛谷P2197 nim游戏(Nim游戏)
题目描述 甲,乙两个人玩Nim取石子游戏. nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取完,不能不取.每次只能从一堆里 ...
- [洛谷P2197]nim游戏
题目大意:Nim游戏.地上有n堆石子,每人每次可从任意一堆石子里取出任意多石子,不能不取,且每次只能从一堆里取.没石子可取的人输.问是否存在先手必胜的策略. 题解:Nim游戏有一个定理,就是当所有棋子 ...
- P4554 小明的游戏 (洛谷) 双端队列BFS
最近没有更新博客,全是因为英语,英语太难了QWQ 洛谷春令营的作业我也不会(我是弱鸡),随机跳了2个题,难度不高,还是讲讲吧,学学新算法也好(可以拿来水博客) 第一题就是这个小明的游戏 小明最近喜欢玩 ...
- NOIP2012 Day1 T2国王游戏 洛谷P1080
第一篇博客啊…… 由于我太弱了,还要去补不全的知识点准备参加人生第一次NOIp,所以第一篇博客就简短一点好了(偷懒就直说吧……) 洛谷P1080传送门 题意概括: 有N对数ai和bi,以及两个数a0和 ...
- 洛谷P2197 nim游戏模板
Code: #include<iostream> using namespace std; int main(){ int t; cin>>t; while(t--){ int ...
- AC日记——欧几里得的游戏 洛谷 P1290
题目描述 欧几里德的两个后代Stan和Ollie正在玩一种数字游戏,这个游戏是他们的祖先欧几里德发明的.给定两个正整数M和N,从Stan开始,从其中较大的一个数,减去较小的数的正整数倍,当然,得到的数 ...
- 矩阵取数游戏洛谷p1005
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...
随机推荐
- CF 643 E. Bear and Destroying Subtrees
E. Bear and Destroying Subtrees http://codeforces.com/problemset/problem/643/E 题意: Q个操作. 加点,在原来的树上加一 ...
- IOI 2017 Practice Contest mountains
Mountains 题面 题意: 选最多的点使得两两看不见. 分析: 分治,solve(l,r)为区间[l,r]的答案.那么如果不选最高点,分治两边即可,选了最高点,那么在最高点看不见的区间里分治. ...
- PHP中array_reduce()使用
array_reduce — 用回调函数迭代地将数组简化为单一的值 给定一个数组: $ar = array(1,2,3,4,5); 如果要求得这个数组中各个元素之和. 方法一. 很自然的用foreac ...
- FCL中你不得不知的几种委托
FCL中丰富的类库信息极大的方便了我们的编码,很多我们日常经常用到的类型,FCL中已经帮我们定义好,下面要介绍的就是FCL中定义好的几种委托类型,直接使用它们不仅能提高我们的编码效率,而且还能让我们的 ...
- ThinkPHP开启设置子域名笔记
一.ThinkPHP框架里 common下的config文件 'APP_SUB_DOMAIN_DEPLOY' => 1, // 开启子域名配置 'APP_SUB_DOMAIN_RULES' =& ...
- 一种精准monkey测试的方法
WeTest 导读 相信大家都知道移动端应用的monkey测试吧,不知你们有没有为monkey测试的太过于随机性的特性有过困扰,至少在我们这种界面控件较少且控件位置较偏的app的使用上其测试有效性大打 ...
- leetcode-峰值检测
寻找峰值 峰值元素是指其值大于左右相邻值的元素. 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引. 数组可能包含多个峰值,在这种情况下,返回 ...
- sql server存储特殊字符解决办法
好久没来院子了,最近在学java了,再加上项目比较紧,最近都没怎么上,其实这几天在项目中学到不少东西,都能写下来,但是久而久之就忘了,还是得养成及时总结的好习惯啊,还有有时间一定要把那个小项目整理下来 ...
- UVa 1583 - Digit Generator 解题报告 - C语言
1.题目大意 如果a加上a的各个数字之和得到b,则说a是b的生成元.给出n其中$1\le n\le 100000$,求其最小生成元,若没有解则输出0. 2.思路 使用打表的方法打出各个数字a对应的b, ...
- SpringCloud IDEA 教学 (四) 断路器(Hystrix)
写在开始 在SpringCloud项目中,服务之间相互调用(RPC Remote Procedure Call —远程过程调用),处于调用链路底层的服务产生不可用情况时,请求会产生堆积使得服务器线程阻 ...