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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章