bzoj3105 新Nim游戏【线性基+高斯消元】

解题思路:

由于Nim游戏先手必胜的条件是每堆石子Xor和不为0,那么我们要求的即是:剩下最多的石子,且其不存在一个非空子集异或和为0。即求解极大线性无关组。。。

证明是个拟阵(不会证……)

因此只要把a[i]从大到小排序,依次贪心的添加到当前集合就可以了,若其可以成为一个基则剩下,否则拿走。(有点想kruskal啊)

关于高斯消元O(30n)求线性无关组的方法,可以看莫涛的《Xor方程组》。

#include<bits/stdc++.h>
#define ll long long
using namespace std;

int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return  i*f;
}

const int N=105;
int n,a[N],base[30];
ll ans;

bool cmp(const int &a,const int &b)
{
    return a>b;
}


int main()
{
    //freopen("lx.in","r",stdin);
    n=getint();
    for(int i=1;i<=n;i++)a[i]=getint(),ans+=a[i];
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)
    {
        int cur=a[i];
        for(int j=30;j>=0;j--)
            if(cur&(1<<j))
            {
                if(base[j])cur^=base[j];
                else{base[j]=cur;break;}
            }
        if(cur)ans-=a[i];
    }
    cout<<ans;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值