题目描述:
改变Nim游戏的规则
在第一个回合中,第一个游戏者可以直接拿走若干个整堆的火柴。可以一堆都不拿,但不可以全部拿走。第二回合也一样,第二个游戏者也有这样一次机会。从第三个回合(又轮到第一个游戏者)开始,规则和Nim游戏一样。
题目分析:
问题转化为
我们最少取多少的物品,能使剩下的物品不存在异或和为0的子集
首先贪心,先向线性基里填大的数
然后判断新加入的数与线性基里的数有没有线性关系
如果一个数与线性基的数线性相关
那么这个数一定可以被一个子集表示
题目链接:
Ac 代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll long long
int a[110],p[40],n;
inline int insert(int x)
{
for(int i=30;~i;i--)
if((x>>i)&1)
{
if(!p[i])
{
p[i]=x;
return x;
}
x^=p[i];
}
return x;
}
int main()
{
ll tot=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),tot+=a[i];
std::sort(a+1,a+n+1);
ll ans=0;
for(int i=n;i;i--) if(insert(a[i])) ans+=a[i];
if(!ans) printf("-1\n");
else printf("%lld\n",tot-ans);
return 0;
}