0%

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}$

题解

线性基 贪心

线性基模板题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#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;
}

欢迎关注我的其它发布渠道