洛谷P4301 [CQOI2013]新Nim游戏(线性基)
不知道线性基是什么东西的可以看看蒟蒻的总结
后手在什么时候能够获胜呢?只有在他能构造出一个子集的异或和为0时(这个应该是nim博弈的结论了吧)
那么为了必胜,我们就要取到没有子集异或和为0为止
那就是构造一个线性无关,那么构造线性基即可
然后还有一个问题就是石子要取得最小,那么就是留下来的要最大,就是被加进线性基中的要最大
考虑贪心,从大到小取石头,如果不能被线性基中的数表示那么就加入线性基,否则这堆石子就要取走
据说贪心的证明得用拟阵,我还是不会
1 //minamoto 2 #include<cstdio> 3 #include<algorithm> 4 #define ll long long 5 using namespace std; 6 const int N=105; 7 ll b[65],a[N],ans;int n; 8 inline void insert(ll x){ 9 for(int i=63;i>=0;--i) 10 if(x>>i&1){ 11 if(!b[i]) return (void)(b[i]=x); 12 x^=b[i]; 13 } 14 } 15 inline bool find(ll x){ 16 for(int i=63;i>=0;--i) 17 if(x>>i&1){ 18 if(!b[i]) break; 19 x^=b[i]; 20 } 21 return x; 22 } 23 int main(){ 24 scanf("%d",&n); 25 for(int i=1;i<=n;++i) scanf("%lld",&a[i]); 26 sort(a+1,a+1+n); 27 for(int i=n;i;--i) 28 if(find(a[i])) insert(a[i]); 29 else ans+=a[i]; 30 printf("%lld\n",ans); 31 return 0; 32 }
深深地明白自己的弱小