XOR( 异或空间

XOR

# 题意

给出$n$个数,$a_{i}$从中选取一些进行异或运算(可以只有一个),求出他们所有可能组合得到的异或值去重后的第$k$小的值

$1 \leqslant a_{i} \leqslant 10^{18}$

# 题解

因为是去重后的值所以求出线性基然后组合即可

因为$1 \leqslant a_{i} \leqslant 10^{18}$即所有数都在二进制$64$位之间,可以将每个数看做是$64$位二进制数,通过高斯消元后求得简化的行阶梯型矩阵,

即线性基,矩阵的秩为$r$,首先最大的数即所有数异或,其余的都是组合,一共有$2^{r}$种,这里是包含了值为$0$的项,

需要判断是否存在$0$,因为题目中不会选出$a_{i} \oplus a_{i}$所以不一定存在$0$,在高斯消元后如果存在$0$,即说明存在几个数异或等于$0$

将$k-1$即可,然后通过二进制求出第$k-1$小的数,如果 $k \geqslant 2^{t}$ 即没有这么多不同的值就输出$-1$

 1 #include <bits/stdc++.h>
 2 #define ull long long
 3 using namespace std;
 4 const int N=1e4+10;
 5 int n,m;
 6 ull a[N];
 7 int main() {
 8     int t;
 9     cin >> t;
10     for (int T = 1; T <= t; T++) {
11         cin >> n;
12         for (int i = 1; i <= n; i++)
13             cin >> a[i];
14         bool zero = 0;
15         int r = n;
16         for (int i = 1; i <= n; i++) {
17             for (int j = i + 1; j <= n; j++)
18                 if (a[j] > a[i]) swap(a[i], a[j]);
19 
20             if (a[i] == 0) {//最大的主元为0后面的肯定也是0
21                 r = i - 1;
22                 zero = 1;
23                 break;
24             }
25             for (int k = 63; k >= 0; k--)
26                 if (a[i] >> k & 1) {
27                     for (int j = 1; j <= n; j++)
28                         if (j != i && (a[j] >> k & 1)) a[j] ^= a[i];
29                     break;
30                 }
31         }
32         cin >> m;
33         cout << "Case #" << T << ":" << endl;
34         while (m--) {
35             ull k, ans = 0;
36             cin >> k;
37             if (zero) k--;
38             if (k >= 1llu << r) puts("-1");
39             else {
40                 for (int i = r-1 ; i >= 0; i--)
41                     if (k >> i & 1) ans ^= a[r - i];
42                 cout << ans << endl;
43             }
44         }
45     }
46 }

 

posted @ 2020-04-19 11:45  Hyx'  阅读(359)  评论(0编辑  收藏  举报