bzoj 3105

首先你需要一些Nim游戏的知识!

这里

现在假设你已经会了Nim游戏的知识了

那么我们就可以讨论这道题了

 首先,根据上面提到的:如果所有数量异或和为0,那么这就是不合法的

而且,其实由于后手可以取走一些堆,所以只要是这些堆数量的一个子集异或和为0就是不合法的(因为后手可以把这个子集以外的部分全取走,就变成先手必败的了)

那么就变成裸的线性基问题了

将代价从大到小排序后插入线性基,对于能用线性基中元素表示出的值都先手取走就好

代码:

#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;
int p[32];
int a[101];
int n;
ll ans;
bool get_p(int x)
{
    for(int i=31;i>=0;i--)
    {
        if(!(x&(1<<i)))continue;
        else if(p[i])x^=p[i];
        else {p[i]=x;break;}
    }
    return x==0;
}
bool cmp(int x,int y)
{
    return x>y;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)ans+=1ll*get_p(a[i])*a[i];
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2019-05-06 20:47  lleozhang  Views(185)  Comments(0Edit  收藏  举报
levels of contents