[CQOI2013]新NIM游戏

思路

NIM游戏,先手获胜的条件就是,所以值异或后不为0,也就是在进行完第二轮后,场面不为0即可获胜。
也就是让第二***作的人不能从这若个个数得到0,这个判断就可以用线性基来完成了,
同时我们又要保证第一轮拿的值最小,所以我们考虑贪心,优先把较大的放入线性基
这样我们就会每次都取出符合要求的较小的数字了,然后累加答案即可。

代码

/*
  Author : lifehappy
*/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

struct linearbasis {
    ll base[64], flag, cnt;

    bool add(ll x) {
        for(int i = 62; ~i; i--) {
            if(x >> i & 1) {
                if(!base[i]) {
                    base[i] = x;
                    return true;
                }
                x ^= base[i];
            }
        }
        flag = 1;
        return false;
    }

    ll query_max() {
        ll ans = 0;
        for(int i = 62; ~i; i--) {
            if((ans ^ base[i]) > ans) {
                ans ^= base[i];
            }
        }
        return ans;
    }

    ll query_min() {
        for(int i = 0; i <= 62; i++) {
            if(base[i]) {
                return base[i];
            }
        }
    }

    void rebuild() {
        cnt = 0;
        for(int i = 62; i >= 0; i--) {
            for(int j = i - 1; j >= 0; j--) {
                if(base[i] >> j & 1) {
                    base[i] ^= base[j];
                }
            }
        }
        for(int i = 0; i <= 62; i++) {
            if(base[i]) {
                ll temp = base[i];
                base[i] = 0;
                base[cnt++] = temp;
            }
        }
    }

    ll query_k(ll k) {
        k -= flag;
        if(k == 0) return 0;
        if(k >= 1ll << cnt) return -1;
        ll ans = 0;
        for(int i = 62; ~i; i--) {
            if(k >> i & 1) {
                ans ^= base[i];
            }
        }
        return ans;
    }
    void init() {
        memset(base, 0, sizeof base), flag = cnt = 0;
    }
}a;

int b[110], n;

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &b[i]);
    }
    sort(b + 1, b + 1 + n, greater<int> ());
    ll ans = 0;
    for(int i = 1; i <= n; i++) {
        if(!a.add(b[i])) {
            ans += b[i];
        }
    }
    printf("%lld\n", ans);
    return 0;
}