题目大意:M堆牌,每堆有Ni个,两人轮流取,每次取一堆的任意数量,取完者胜。问先手想赢,第一步有几种方案?
题解:SG定理的巧妙应用
因为每次可以取任意数量,所以sg[i]==i。整个游戏的sg值s=N1^N2^…^Nm;
枚举I到m,设x=s^Ni,(此时x为除了第I堆,其它堆游戏的和的sg值),只要第I堆取了x个,x^其它游戏的和(x)==0,是P状态,所以先手第一步在第I堆取x个就是一种方案(注意判断x是否<=Ni)
代码:
#include<cstdio>
#define MAXN 105
int num[MAXN];
int main()
{
int n,s,ans;
while(1)
{
scanf("%d",&n);
if(!n)break;
s=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
s^=num[i];
}
ans=0;
for(int i=1;i<=n;i++)
if(num[i]>(s^num[i]))
ans++;
printf("%d\n",ans);
}
return 0;
}