\(k\)堆石子,兩我的遊戲:spa
首先,A拿走若干堆石子(不能所有拿走)code
以後,B拿走若干堆石子(不能所有拿走)遊戲
而後從A開始\(Nim\)遊戲。ip
問A能不能取勝。若是能,A第一步至少要拿走多少石子?it
顯然能夠取勝。A拿的只剩1堆,B不能拿走,A全拿完,B輸了。io
考慮A第一次拿完以後,剩下的石子在異或意義下必須線性無關。不然B找出一組石子異或爲0,A就輸掉了。class
那麼A拿走的石子儘可能少等價於剩下的石子儘可能多。im
也就是求最大權線性無關組,權值即爲石子個數。sort
線性無關組是一個擬陣(遺傳性易證,交換性來講,若是兩個線性無關組\(X\)和\(Y\),\(|X|<|Y|\),那麼\(X\)張成的線性空間有\(|X|\)維,\(Y\)張成的線性空間有\(|Y|\)維,後者中必能選出一個元素加到\(|X|\)中線性無關)。di
因此咱們從大到小判斷每堆石子能不能保留便可。
#include <algorithm> #include <cstdio> const int K = 105; int J[32], A[K]; bool mark[K]; bool cmp(int a, int b) { return b < a; } int main() { int k; scanf("%d", &k); for (int i = 0; i < k; ++i) scanf("%d", &A[i]); std::sort(A, A + k, cmp); long long ans = 0; for (int i = 0, j, l; i < k; ++i) { for (l = 31, j = A[i]; ~l; --l) if ((j >> l) & 1) { if (!J[l]) { J[l] = j; break; } else j ^= J[l]; } if (l == -1) ans += A[i]; } printf("%lld\n", ans); return 0; }