bzoj 3105
首先你需要一些Nim游戏的知识!
看这里
现在假设你已经会了Nim游戏的知识了
那么我们就可以讨论这道题了
首先,根据上面提到的:如果所有数量异或和为0,那么这就是不合法的
而且,其实由于后手可以取走一些堆,所以只要是这些堆数量的一个子集异或和为0就是不合法的(因为后手可以把这个子集以外的部分全取走,就变成先手必败的了)
那么就变成裸的线性基问题了
将代价从大到小排序后插入线性基,对于能用线性基中元素表示出的值都先手取走就好
代码:
#include <cstdio> #include <algorithm> #define ll long long using namespace std; int p[32]; int a[101]; int n; ll ans; bool get_p(int x) { for(int i=31;i>=0;i--) { if(!(x&(1<<i)))continue; else if(p[i])x^=p[i]; else {p[i]=x;break;} } return x==0; } 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++)ans+=1ll*get_p(a[i])*a[i]; printf("%lld\n",ans); return 0; }