bzoj3105: [cqoi2013]新Nim游戏

当年的我还是太naive啊。还以为是线性基sb题

对于先手的选择是非常重要的,我们必须控制对手无法把剩下的石子堆取出一部分使得异或和为0

意思就是取剩下的石子堆无法找到一个异或和为0的子集,判定方法即为线性基

除此之外还要去掉最少,而这又等于保留最多

考虑使用拟阵,子集限制即为异或和为0,遗传性显然,证明一下交换性:若|A|<|B|,在线性基中A的元素个数必定少于B,只要在B的基中随便找一个A不是1自己是1的位就行了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;

int a[110],lt[110];LL ans;
bool cmp(int a1,int a2){return a1>a2;}
bool insert(int d)
{
    for(int i=30;i>=0;i--)
        if(d&(1<<i))
        {
            if(lt[i]==0)
                {lt[i]=d;return true;}
            else
                d^=lt[i];
        }
    return false;
}
int main()
{
    int n,x;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    sort(a+1,a+n+1,cmp);
    
    ans=0;
    for(int i=1;i<=n;i++)
        if(!insert(a[i]))ans+=(LL(a[i]));
    
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2019-01-14 11:40  AKCqhzdy  阅读(153)  评论(0编辑  收藏  举报