Yukicoder No.184 たのしい排他的論理和(HARD)

,

https://yukicoder.me/problems/no/184

ちょっと好き。

solution

$64$要素のvectorの次元を数える問題。$O(N)$。

集合を用意し、線形独立を保つまま要素を足していく。 結果の集合の要素数、つまり次元$d$に対し$2^d$が答え。 線形独立性の判定は掃き出し法、特に前進消去部分をする。

implementation

#include <iostream>
#include <vector>
#include <algorithm>
#define repeat(i,n) for (int i = 0; (i) < int(n); ++(i))
#define repeat_reverse(i,n) for (int i = (n)-1; (i) >= 0; --(i))
#define whole(f,x,...) ([&](decltype((x)) whole) { return (f)(begin(whole), end(whole), ## __VA_ARGS__); })(x)
using namespace std;
uint64_t bit(int i) { return 1ull << i; }
void add(vector<uint64_t> & xs, uint64_t y) {
    for (uint64_t x : xs) {
        repeat_reverse (i,64) {
            if (not (x & bit(i)) and not (y & bit(i))) continue;
            if ((x & bit(i)) and (y & bit(i))) y ^= x;
            break;
        }
    }
    if (y) {
        xs.push_back(y);
        whole(sort, xs);
        whole(reverse, xs);
    }
}
int main() {
    int n; cin >> n;
    vector<uint64_t> acc;
    repeat (i,n) {
        uint64_t a; cin >> a;
        add(acc, a);
    }
    cout << (1ll << acc.size()) << endl;
    return 0;
}