LOJ #113. 最大异或和 (线性基)

题目链接:#113. 最大异或和

题目描述

这是一道模板题。

给由 \(n\) 个数组成的一个可重集 \(S\),每次给定一个数 \(k\),求一个集合 \(T \subseteq S\),使得集合 \(T\)\(S\) 的所有非空子集的不同的异或和中,其异或和 \(T_1\ xor\ T_2\ xor\ ... \ xor\ T_{|T|}\) 是第 \(k\) 小的。

输入格式

第一行一个数 \(n\)

第二行 \(n\) 个数,表示集合 \(S\)

第三行一个数 \(m\),表示询问次数。

第四行 \(m\) 个数,表示每一次询问的 \(k\)

输出格式

输出 \(m\) 行,对应每一次询问的答案,第 \(k\) 小的异或和。如果集合 \(S\) 的所有非空子集中,不同的异或和数量不足 \(k\),输出 \(-1\)

样例

样例输入

3
1 2 3
5
1 2 3 4 5

样例输出

0
1
2
3
-1

数据范围与提示

\(1\le n,m\le 10^5, 0\le S_i\le 2^{50}\)

题解

线性基 贪心

线性基模板题。

#include 
using namespace std;
typedef long long ll;
using ll = long long;
const int maxn = 5e5 + 5;
const int maxbit = 63; // long long 最大 2^63 - 1. 最多 63 位. 用数组表示为 0 ~ 62.

ll p[maxbit];

void add(ll x) {
    for(int i = maxbit - 1; i >= 0; --i) {
        if((x >> i) & 1) {
            if(p[i] == 0) {
                p[i] = x;
                break;
            }
            x ^= p[i];
        }
    }
}

int main() {
    std::ios::sync_with_stdio(false);
    int n;
    cin >> n;
    for(int i = 1; i <= n; ++i) {
        ll x;
        cin >> x;
        add(x);
    }

    ll ans = 0;
    for(int i = maxbit - 1; i >= 0; --i) {
        if((ans ^ p[i]) > ans) {
            ans ^= p[i];
        }
    }
    cout << ans << endl;
    return 0;
}

转载于:https://www.cnblogs.com/wulitaotao/p/11423728.html

你可能感兴趣的:(LOJ #113. 最大异或和 (线性基))