HDU1907
HDU2509
题意:n堆物品,两人轮流拿,每次再一堆中最少拿一个,最多拿完,拿完的获胜,问谁获胜。
分析:反尼姆博弈的先手必胜态:
1.每堆都只有一个,只有偶数堆(尼姆和为0);
2.存在物品个数大于一个的堆,并且尼姆和不为0.
第一种情况好理解;
第二种情况当前尼姆和不为0,一定有一种拿法使得尼姆和为0,并且尼姆和为0的时候没有拿法使尼姆和还是0(证明见链接中取火柴的游戏),也就是说先后手面临的情况是这样的:
先手非0->后手0->先手非0->后手0->…直到只剩下一个物品数大于1的堆,这时先手将该堆剩下1个转化成自己必胜的情况(可以控制剩下一个或者零个使对方必败)。
2509规则稍有不同,能够拿中间的几个使某堆拿完后变成两堆,如@@@,拿走中间的一个,成为@ @,但是这样也不能拿一次使尼姆和为0的状态还是保持尼姆和为0,(看完上面情况的证明就明白了)
2509的AC代码:
#include<cstdio>
using namespace std;
int main()
{
int n, nim, a[105];
bool flag;
while(~scanf("%d", &n))
{
flag = 0;
nim = 0;
for(int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
if(a[i] != 1)
{
flag = 1;
}
nim ^= a[i];
}
if(flag)
{
if(nim == 0)
printf("No\n");
else
printf("Yes\n");
}
else
{
if(nim == 0)
printf("Yes\n");
else
printf("No\n");
}
}
return 0;
}