Step1 Problem:
Nim 博弈:有 n 堆石头,两个人轮流拿,每次从每堆至少拿一个,拿走最后一个石头的获胜。
Nim 博弈,问你先手第一步有多少种方式,可以使得自己获胜。
Step2 Ideas:
Nim 博弈:异或和为 0 必败,否则必胜。
异或和不为 0,可以从某些堆拿走一定数量的石子使得其变为 异或和为 0.
a^tmp = res <-> a = res ^ tmp. 这题我们需要用到这个定理
我们求出异或和 = res。
判断 a[i] 这堆能否拿走一些石头,使得异或和为 0。
除了 a[i] 以外的所有堆异或和 = res ^ a[i]. 我们要让 a[i] 变成 res ^ a[i],这样才能使得异或和为 0.
所以 a[i] > res ^ a[i] 才可以。
Step3 Code:
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
const int N = 1e3+5;
ll a[N];
int main()
{
int n;
while(~scanf("%d", &n) && n)
{
ll t = 0, num;
for(int i = 0; i < n; i++)
scanf("%lld", a+i), t ^= a[i];
if(!t) printf("0\n");
else {
int ans = 0;
for(int i = 0; i < n; i++)
{
//printf("%lld %lld\n", t^a[i], a[i]);
if((t^a[i]) < a[i])
ans++;
}
printf("%d\n", ans);
}
}
return 0;
}