题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3105
首先,要先手必胜,就不能取后让剩下的火柴中存在异或和为0的子集,否则对方可以取成异或和为0的状态,那么必败;
可以贪心地从大到小排序,如果一堆火柴可以被之前的一些火柴堆(基)异或表出,那么这堆火柴必须拿走;
证明好像是拟阵什么的,不会...
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int n,a[105],b[35]; ll ans; bool cmp(int x,int y){return x>y;} int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++) { int t=a[i]; for(int j=30;j>=0;j--) if(a[i]&(1<<j)) { if(!b[j]){b[j]=i; break;} a[i]^=a[b[j]]; } if(a[i]==0)ans+=t; } printf("%lld",ans); return 0; }