Being a Good Boy in Spring Festival

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7382    Accepted Submission(s): 4490

Problem Description
一年在外 父母时刻牵挂
春节回家 你能做几天好孩子吗
寒假里尝试做做下面的事情吧

陪妈妈逛一次菜场
悄悄给爸爸买个小礼物
主动地 强烈地 要求洗一次碗
某一天早起 给爸妈用心地做回早餐

如果愿意 你还可以和爸妈说
咱们玩个小游戏吧 ACM课上学的呢~

下面是一个二人小游戏:桌子上有M堆扑克牌;每堆牌的数量分别为Ni(i=1…M);两人轮流进行;每走一步可以任意选择一堆并取走其中的任意张牌;桌子上的扑克全部取光,则游戏结束;最后一次取牌的人为胜者。
现在我们不想研究到底先手为胜还是为负,我只想问大家:
——“先手的人如果想赢,第一步有几种选择呢?”

 
Input
输入数据包含多个测试用例,每个测试用例占2行,首先一行包含一个整数M(1<M<=100),表示扑克牌的堆数,紧接着一行包含M个整数Ni(1<=Ni<=1000000,i=1…M),分别表示M堆扑克的数量。M为0则表示输入数据的结束。
 
Output
如果先手的人能赢,请输出他第一步可行的方案数,否则请输出0,每个实例的输出占一行。
 
Sample Input
3
5 7 9
0
 
Sample Output
1
 
Author

题意: 二人小游戏:m堆扑克牌,每次可以取其中一堆中的任意张,最后没有牌取了则为败者(即最后一次取牌的人为胜者)。这道题不是简单的直接判断是否先手能够获胜,而是求如果先手能够获胜,那么第一步有多少种可行方案数。如果先手不能获胜,输出0。
思路:
1.先直接求出先手是否能够获胜,方法是

对于一个Nim游戏的状态(a1,a2,...,an),如果a1^a2^...^an=0 ,那么先手必败。(也就是说,a1^a2^...^an !=0,那么先生必胜)
2.看能否通过减少其中某一堆的数量,使其变成必败状态。
令当前状态为sum,
如果能够获胜,那么sum = a1^a2^...^an   != 0;
现在从第1堆开始看,能否通过减少第1堆中牌的数量(因为只能取牌,所以是减少牌的数目),使状态变为必败状态,
如果想让下一个状态为必败状态,那么只要让 a1' =a2^a3^...^an  即可(此时 ,a1'^a2^...^an  =(a2^a3^...^an)^(a2^a3^...^an)
=  0  ,状态变为必败状态)
那么问题来了,当前牌的数目能变成 a1' 吗?也就是说a1能变成
a1' 吗?
这里只需要判断 a1 大于
a1' 就可以了:  
a1 大于
a1',可以减少第1堆牌的数目变成必败状态。否则,不能。
相应的,通过判断 ai 大于
ai' :   ai大于ai',可以减少第i堆牌的数目变成必败状态。否则,不能。

hint:这里在求ai' 的时候不必每次都求  a1^a2^...^ai -1 ^ ai +1^...^an ,而是利用第1步求出来的
当前状态       sum =         a1^a2^...^an ,两边异或a1,
                 a1^sum =
a1^ a1^a2^...^an  =
a2^...^an
  = a1' 
a1' =a1 ^ sum
相应的          sum =         a1^a2^...^ ai^...^an ,两边异或 ai,
                ai^sum = a1^a2^...^ai ^ai ^...^an  = ai'
ai' = ai ^ sum
推出,如果 (ai^sum) < ai ,那么方案可行。

代码:

#include<iostream>
#include<cstdio>
using namespace std; int main(){
int ni[110];
int m;
int i;
int sum;//状态
int ans;//可行的方案数
while(scanf("%d",&m),m){
sum=0;//初始化为0
for(i=0;i<m;i++){
scanf("%d",&ni[i]);
sum=sum^ni[i];
}
if(sum){
ans=0;
for(i=0;i<m;i++){
if((sum^ni[i])<ni[i]){//第i堆的数目多,可以减少第i堆数目,变成必败状态
ans++;
}
}
printf("%d\n",ans);
}
else{
printf("%d\n",0);
}
}
return 0;
}

HDU 1850 Being a Good Boy in Spring Festival(博弈·Nim游戏)的更多相关文章

  1. HDU 1850 Being a Good Boy in Spring Festival (Nim博弈)

    Being a Good Boy in Spring Festival Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32 ...

  2. hdu 1850 Being a Good Boy in Spring Festival(Nimm Game)

    题意:Nimm Game 思路:Nimm Game #include<iostream> #include<stdio.h> using namespace std; int ...

  3. HDU.1850 being a good boy in spring festival (博弈论 尼姆博弈)

    HDU.1850 Being a Good Boy in Spring Festival (博弈论 尼姆博弈) 题意分析 简单的nim 博弈 博弈论快速入门 代码总览 #include <bit ...

  4. HDU 1850 Being a Good Boy in Spring Festival

    此题先考虑第一种,5 7 9的情况,先手如果想赢,则必定要把异或值变为0,因为随便取,所以此处的异或指的是对堆中的石子数进行异或,而非异或其SG函数. 首先7^9=14,因为要异或为0,则5要变成14 ...

  5. hdu 1850 Being a Good Boy in Spring Festival 博弈论

    求可行的方案数!! 代码如下: #include<stdio.h> ]; int main(){ int n,m; while(scanf("%d",&n)&a ...

  6. HDOJ HDU 1850 Being a Good Boy in Spring Festival

    Description 一年在外 父母时刻牵挂 春节回家 你能做几天好孩子吗 寒假里尝试做做下面的事情吧 陪妈妈逛一次菜场 悄悄给爸爸买个小礼物 主动地 强烈地 要求洗一次碗 某一天早起 给爸妈用心地 ...

  7. HDU 1850 Being a Good Boy in Spring Festival 在春节做乖孩子(Nim博弈,微变形)

    题意: 思路: 如果全部扑克牌数目异或的结果ans为0,则必输,输出0.否则,必须要给对方一个P状态,可以对所有扑克堆进行逐个排查,将ans^a[i]就可以得到除了a[i]之外其他扑克数的异或结果tm ...

  8. 题解报告:hdu 1850 Being a Good Boy in Spring Festival(尼姆博弈)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1850 Problem Description 一年在外 父母时刻牵挂春节回家 你能做几天好孩子吗寒假里 ...

  9. HDU1850 Being a Good Boy in Spring Festival(博弈)

    Being a Good Boy in Spring Festival Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I ...

随机推荐

  1. apache hadoop 2.4.0 64bit 在windows8.1下直接安装指南(无需虚拟机和cygwin)

    工作须要.要開始搞hadoop了,又是大数据,自己感觉大数据.云.仅仅是ERP.SOAP风潮之后与智能地球一起诞生的概念炒作. 只是Apache是个奇妙的组织.Java假设没有它也不会如今如火中天.言 ...

  2. wcf上传字节数组报错问题

    为了实现上传大文件所以我们要如下设置最大值,其中security是设置访问服务的认证,此处是把它设置成为不认证,transferMode就是设置运用流的模式 <webHttpBinding> ...

  3. vim 处理换行符

    1. 设置文件格式 :set fileformats=unix,dos 2. 查询当前文件格式 :set fileformat? 3. 转换文件格式 :set fileformat=dos 4. 设置 ...

  4. Android 开发资源

    0x00 Android 入门资料 a. Android 学习之路 b.<第一行代码> 介绍及购买链接:http://blog.csdn.net/guolin_blog/article/d ...

  5. HDU 2242 考研路茫茫——空调教室(边双连通)

    HDU 2242 考研路茫茫--空调教室 题目链接 思路:求边双连通分量.然后进行缩点,点权为双连通分支的点权之和,缩点完变成一棵树,然后在树上dfs一遍就能得出答案 代码: #include < ...

  6. string去空格

    众所周知,string字符串去除空格的方法有trim()和replace(),区别在于trim()去首尾的空格,但是不能去中间的,而replace可以去除所有的空格. string data1=&qu ...

  7. android的Environment类 Android存储访问及目录

    http://www.cnblogs.com/mengdd/p/3742623.html http://blog.csdn.net/barnett_zhubo/article/details/6832 ...

  8. ios - UISearchBar输入框背景色

    //输入框背景色 bar.searchBarStyle = UISearchBarStyleMinimal; [bar positionAdjustmentForSearchBarIcon:UISea ...

  9. phthon 基础 7.3 logging 日志模块

    一. logging 的使用 日志是我们排查问题的关键利器,写好日志记录,当我们发生问题时,可以快速定位代码范围进行修改.python有给我们开发者提供好的日志模块,下面我们就来介绍一下logging ...

  10. EasyNVR RTSP转RTMP-HLS流媒体服务器前端构建之_关于接口调用常见的一些问题(401 Unauthorized)

    在之前的博客<EasyNVR H5流媒体服务器方案架构设计之视频能力平台>中我们描述了EasyNVR的定位,作为一个能力平台来进行功能的输出: 也就是说,在通常情况下,我们将一套视频的应用 ...