思路:
可以构造出0 ~ -1 的充要条件是有x个异或运算线性无关的数在0~-1之间, 原因是k个线性无关可以构造个不同的数。
于是求得尽量大的x对数构造即可, 求得时候可以考虑高斯消元法,就是线性基的构造方法
假设基内的数为,,…, 新加入数k, 让k取得尽可能小的数,在线性基中就是不断异或取小值。
构造数列可以考虑对称的方式构造,将数看做2进制就类似 0 -> 0 | 1 -> 00 01 | 11 10的方式, 也可以考虑dfs构造。
#include<bits/stdc++.h>
using namespace std;
vector<int> V;
vector<int> B, B1;
void add(int k) {
int t = k;
for (auto v : B) k = min(k, k^v);
if (k > 0) {
B.emplace_back(k);
B1.emplace_back(t);
sort(B.begin(), B.end(), greater<int>());
}
}
void construct(int x) {
V.emplace_back(0);
for (int i = 0; i < x; i++) {
for (int j = (1<<i)-1; j>=0 ; j--) {
V.emplace_back(V[j] ^ B1[i]);
}
}
for (auto k : V) cout << k << " ";
cout << endl;
}
int main() {
ios::sync_with_stdio(false);
int n; cin >> n;
V.resize(n);
for (int i = 0; i < n; i++) cin >> V[i];
sort(V.begin(), V.end());
int x = 0, k=0;
for (int i = 1; i < 22; i++) {
for (; k<V.size() && V[k] < (1 << i); k++) {
add(V[k]);
}
if (B.size() == i) x = i;
}
B.clear();
for (int i = 0; i<V.size()&&V[i] < (1 << x); i++)
add(V[i]);
V.clear();
cout <<x<< endl;
construct(x);
}