《编程之美》第1.12节:NIM(2)"拈"游戏分析
如果石头总数N是偶数,则后动手的人能赢;如果石头数时奇数,则先动手的人赢,先动手的人只要保证每次取完石头以后,每堆石头的总数异或后得1即可。
下面程序给出当N是奇数时,应该如何选取,函数返回值pair<int,int>中first表示取第i堆,i从0开始,second表示把第i堆变成的数,即剩下的数时divided[i]-second。
#include<iostream>
#include<vector>
using namespace std;
pair<int,int> takeTheNHeapNum(vector<int> ÷d)
{
int XOR=0;
for(int i=0;i<divided.size();i++)
XOR^=divided[i];
if(XOR==0)
return pair<int,int>(INT_MAX,INT_MAX);
int maxBit=0;
for(int i=1;i<32;i++)
if((XOR>>i)==0)
{
maxBit=i-1;//找到最高位
break;
}
int result=0;
for(int i=0;i<divided.size();i++)
if((divided[i]>>maxBit)&1)//如果当前值的maxBit位为1,只需要修改这个数
{
result=divided[i];
for(int j=0;j<=maxBit;j++)
{
if(XOR&(1<<j))//遇到XOR的位为1,则result当前位取反
result^=(1<<j);
}
return pair<int,int>(i,result);
}
}
int main()
{
int A[]={1,2,6};
vector<int> devided(A,A+3);
pair<int,int> result=takeTheNHeapNum(devided);
system("pause");
return 0;
}