poj 2975 Nim(博弈+异或和)
http://poj.org/problem?id=2975
题目描述:
有n堆石子,每次从一堆中拿石子,问是否是必胜,如果不是输出0,是就输出拿一次后依然是必胜的方法数。
思路:
由Nimm游戏可知,n堆石子异或和不为0的时候为必胜状态。所以我们要在其中一堆中拿若干个后让异或和为0。
首先对异或和res来说,如果你从res取出a舍弃,剩下的异或和就变成res^a,同样再res中加入a,也是变成res^a。
每堆记为a[i],只要res^a[i]<a[i],就ans++。
因为只要让这堆剩下res^a[i],总的异或和就相当于取出a[i]再放入res^a[i],即总的异或和变成(res^a[i])^(res^a[i])=0。
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<sstream> #include<vector> #include<stack> #include<deque> #include<cmath> #include<map> #include<queue> #include<bitset> //#include<hash_map> #define sd(x) scanf("%d",&x) #define lsd(x) scanf("%lld",&x) #define ms(x,y) memset(x,y,sizeof x) #define fu(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) #define all(a) a.begin(),a.end() #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 using namespace std; //using namespace __gnu_cxx; typedef long long ll; typedef unsigned long long ull; typedef long double ld; const int maxn=1e5+79; const int mod=998244353; const ll INF=0x7f7f7f7f; const double pi=acos(-1); bool cmp(int a,int b) { return a>b; } int n,a[maxn]; int main() { while(1) { sd(n);if(n==0) break; int res=0; fu(i,1,n) { sd(a[i]);res^=a[i]; } int ans=0; fu(i,1,n) { if((res^a[i])<a[i]) ans++; } printf("%d\n",ans); } return 0; }