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

数据范围与提示

(1le n,mle 10^5, 0le S_ile 2^{50})

题解

线性基 贪心

线性基模板题。

#include <bits/stdc++.h>
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