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;
}

 

posted on 2020-08-13 11:49  Aminers  阅读(209)  评论(0编辑  收藏  举报

导航