BZOJ3105 [cqoi2013]新Nim遊戲

Description

\(k\)堆石子,兩我的遊戲:spa

  • 首先,A拿走若干堆石子(不能所有拿走)code

  • 以後,B拿走若干堆石子(不能所有拿走)遊戲

  • 而後從A開始\(Nim\)遊戲。ip

問A能不能取勝。若是能,A第一步至少要拿走多少石子?it

Solution

顯然能夠取勝。A拿的只剩1堆,B不能拿走,A全拿完,B輸了。io

考慮A第一次拿完以後,剩下的石子在異或意義下必須線性無關。不然B找出一組石子異或爲0,A就輸掉了。class

那麼A拿走的石子儘可能少等價於剩下的石子儘可能多。im

也就是求最大權線性無關組,權值即爲石子個數。sort

線性無關組是一個擬陣(遺傳性易證,交換性來講,若是兩個線性無關組\(X\)\(Y\)\(|X|<|Y|\),那麼\(X\)張成的線性空間有\(|X|\)維,\(Y\)張成的線性空間有\(|Y|\)維,後者中必能選出一個元素加到\(|X|\)中線性無關)。di

因此咱們從大到小判斷每堆石子能不能保留便可。

Code

#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;
}
相關文章
相關標籤/搜索