线性基
题意说前两回合双方都只能拿若干堆或不拿但不能拿完,所以要必胜就需要使第一轮拿完后剩下的堆的集合里没有一个子集的异或和为0
然后就可以线性基+贪心,使剩下集合和最大就是第一次拿的最少的解
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
void read(int &x)
{
char c;
while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9')(x*=10)+=c-'0';
}
const int maxn = 110;
struct node
{
int x,c;
}a[maxn];
int n;
int dig[33];
bool cmp(node x,node y){return x.c>y.c;}
int main()
{
ll r1=0,r2=0;
read(n);
for(int i=1;i<=n;i++) read(a[i].x),a[i].c=a[i].x,r1+=a[i].c;
sort(a+1,a+n+1,cmp);
memset(dig,0,sizeof dig);
for(int i=1;i<=n;i++)
{
for(int j=30;j>=0;j--)
if(a[i].x&(1<<j))
{
if(!dig[j]) { dig[j]=a[i].x; r2+=a[i].c; break; }
else a[i].x^=dig[j];
}
}
printf("%lld\n",r1-r2);
return 0;
}