目录
显示
题目链接
https://www.luogu.org/problem/P4301
题解
根据 Nim 游戏的结论,我们不能给对手留下任何一个异或和为 0 的子集,否则对手就可以取走不属于这个子集的其他石子,从而给我们留下必败局面。
考虑使用线性基。我们先对所有火柴按从大到小的顺序排序。先尝试插入最大的数字,如果不能插入这个数字,就把这个数字累加到答案中。
#include <iostream> #include <algorithm> using namespace std; int a[105],p[35]; bool cmp(int a,int b) { return a>b; } bool find(int x) { for(int i=30;i>=0;i--) if((x>>i)&1) { if(!p[i])break; else x^=p[i]; } return x>0; } void add(int x) { for(int i=30;i>=0;i--) if((x>>i)&1) { if(p[i])x^=p[i]; else { p[i]=x; break; } } } int main() { long long k,ans=0; cin>>k; for(int i=1;i<=k;i++) cin>>a[i]; sort(a+1,a+k+1,cmp); for(int i=1;i<=k;i++) if(find(a[i]))add(a[i]); else ans+=a[i]; cout<<ans<<endl; return 0; }