首页 > 其他分享 >hud:Being a Good Boy in Spring Festival(nim博弈方法数计算)

hud:Being a Good Boy in Spring Festival(nim博弈方法数计算)

时间:2022-12-03 13:35:23浏览次数:46  
标签:hud Boy Good 输出 int 先手 while ans er

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,每个实例的输出占一行。


输入样例

3
5 7 9
0
 

输出样例

1


Nim的ans=g1^...gi^gn;ans=0时必败点
方法数与ans的最高位上1的个数相同
附ac代码
#include<bits/stdc++.h>
using namespace std;
int er[110][40];
void turn(int i,int t)
{
    int z=0;
    while(t>0)
    {
        er[i][z++]=t%2;
        t/=2;
    }
}
int turn1(int t)
{
    int z=0;
    while(t>0)
    {
        z++;
        t/=2;
    }
    return z-1;
}
int main(void)
{
   int m;
   while(scanf("%d",&m),m)
   {
   int k;
   int ans=0,maxn=-1,w,sum=0;
   memset(er,0,sizeof(er));
   for(int i=0;i<m;++i)
   {
       scanf("%d",&k);
       ans^=k;
       turn(i,k);
   }
   if(ans==0)
   {
       printf("0\n");
       continue;
   }
   else
   {
       w=turn1(ans);
       for(int i=0;i<m;++i)
       if(er[i][w]==1)
        sum++;    
    printf("%d\n",sum);
   }
   }
   return 0;
}

 

 

标签:hud,Boy,Good,输出,int,先手,while,ans,er
From: https://www.cnblogs.com/ruoye123456/p/16947473.html

相关文章