题目是这样的,两个人玩一种取火柴的游戏,火柴有若干堆,某个人去取时,可以从某一堆中取若干
根,谁最后把所有的火柴取完谁就是胜者。接着给出几组数据,对于每一组数据,第一个数 n 为火柴的堆数,
接下来的 n 个数据为每一堆火柴的数量,如果最终第一个取火柴的人会获胜,则输出 Yes,否则输出 No。
这显然是一个取子问题,如果这两个人都知道取的策略,我们可以知道结改局在取之前就可以定下来。
如果这几堆火柴是非平衡的,那么第一个取的人可以取若干根火柴使它达到平衡,到最后这个人毕然会赢。反
之,如果火柴刚开始就是平衡的,那么第一个人一取就破坏了平衡,从而让另外一个人赢了。
怎样来判断这几堆火柴是否是平衡的呢,有人已经总结出来了,请看下面。
具体的操作我们可以用位运算来实现:
#include <iostream>
using namespace std;
int an[]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824};
int main()
{
int n;
while(cin>>n)
{
int str[30];
for(int k=0;k<n;++k)
cin>>str[k];
int i=0;
for(i=0;i<31;++i)
{
int sum = 0;
for(int j=0;j<n;++j)
{
int c = an[i]&str[j];
if(c != 0)
sum++;
}
//cout<<sum<<endl;
if(sum%2 !=0 )
{
cout<<"Yes"<<endl;
break;
}
}
if(i == 31)
cout<<"No"<<endl;
}
return 0;
}
根,谁最后把所有的火柴取完谁就是胜者。接着给出几组数据,对于每一组数据,第一个数 n 为火柴的堆数,
接下来的 n 个数据为每一堆火柴的数量,如果最终第一个取火柴的人会获胜,则输出 Yes,否则输出 No。
这显然是一个取子问题,如果这两个人都知道取的策略,我们可以知道结改局在取之前就可以定下来。
如果这几堆火柴是非平衡的,那么第一个取的人可以取若干根火柴使它达到平衡,到最后这个人毕然会赢。反
之,如果火柴刚开始就是平衡的,那么第一个人一取就破坏了平衡,从而让另外一个人赢了。
怎样来判断这几堆火柴是否是平衡的呢,有人已经总结出来了,请看下面。
现在考虑各大堆大小分别为N1,N2,……Nk的一般的Nim取子游戏。将每一个数Ni表示为其二进制数(数的位数相等,不等时在前面补0):
N1 = as…a 1a 0
N2 = bs…b1b0
……
Nk = ms…m 1m 0
如果每一种大小的子堆的个数都是偶数,我们就称Nim取子游戏是平衡的,而对应位相加是偶数的称为平衡位,否则称为非平衡位。因此,Nim取子游戏是平衡的,当且仅当:
as + bs + … + ms 是偶数
……
a1 + b1 + … + m1 是偶数
a0 + b0 + … + m0是偶数
具体的操作我们可以用位运算来实现:
#include <iostream>
using namespace std;
int an[]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824};
int main()
{
int n;
while(cin>>n)
{
int str[30];
for(int k=0;k<n;++k)
cin>>str[k];
int i=0;
for(i=0;i<31;++i)
{
int sum = 0;
for(int j=0;j<n;++j)
{
int c = an[i]&str[j];
if(c != 0)
sum++;
}
//cout<<sum<<endl;
if(sum%2 !=0 )
{
cout<<"Yes"<<endl;
break;
}
}
if(i == 31)
cout<<"No"<<endl;
}
return 0;
}