bzoj3105 新Nim游戏
题目大意:给定n堆火柴,第一二次取的时候可以取走任意堆,然后和普通的游戏一样,问怎样取能先手必胜,最小化第一次取的火柴数。
思路:第一次取走后,剩下的火柴中不存在一个子集异或和为0(用线性基判断这件事),贪心能取就取,总和减去剩下的就可以了。实现的时候我们是用别的数来异或当前为上为1的那个最大数,而不是反之。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define maxnode 105 #define LL long long using namespace std; int a[maxnode]={0},ci[maxnode]={0},ins[50]={0}; int main() { int k,i,j,p;LL sum=0,ans=0; scanf("%d",&k); for (i=1;i<=k;++i) scanf("%d",&a[i]); sort(a+1,a+k+1); for (i=1;i<=k;++i) sum+=(ci[i]=a[i]); for (i=k;i>=1;--i) { for (j=29;j>=0;--j) if (a[i]&(1<<j)) { if (!ins[j]) { ins[j]=i;break; } else a[i]^=a[ins[j]]; } if (a[i]) ans+=ci[i]; } printf("%I64d\n",sum-ans); }
时间: 2024-10-07 04:50:30