codeforces 1163E Magical Permutation

思路:
可以构造出0 ~ 2x2^x-1 的充要条件是有x个异或运算线性无关的数在0~2x2^x-1之间, 原因是k个线性无关可以构造2k2^k个不同的数。
于是求得尽量大的x对数构造即可, 求得时候可以考虑高斯消元法,就是线性基的构造方法
假设基内的数为s1s_1,s2s_2,…,sns_n 新加入数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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章