Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Track one bit at a time. A bit contributes to for exactly the prefixes before the first chosen number that has a in that bit.
So if firstZero[b] is the first index where bit is , then
The whole problem is about delaying these first zeros.
The first number has to be , because it is the only number with all bits set. After that, once a bit becomes in the running AND, it is dead forever. No necromancy, no second chances.
To maximize the score, you should kill at most one new bit at each early step. That means the first prefix AND values should have popcounts
This is the maximum possible because after the first element, every new chosen number must differ from all-ones and therefore must kill at least one currently alive bit until none remain.
For lexicographic minimum among optimal permutations, greedily choose the smallest unused number that kills exactly one currently alive bit. This produces
then append all unused numbers in increasing order.
Let and let
We need maximize
The important move is to stop thinking about whole masks and split the score by bits.
Bit contribution
Fix a bit . This bit contributes to exactly while every selected number has bit equal to .
The first time we choose a number with bit , that bit disappears from the running AND forever. Bitwise AND is brutal like that.
Let be the first index such that bit of is . Then bit contributes to exactly the prefixes
so it contributes total.
Therefore
So the job is: delay the first zero of every bit as much as possible.
Maximum possible score
The first element must be , the all-ones mask. Otherwise some bit has first zero at index , which is obviously worse, and no later number can bring that bit back.
After choosing , every other number has at least one zero bit. As long as the current AND still has some alive bit, the next chosen number must kill at least one alive bit unless it has all those alive bits set.
But here is the catch: to keep the score as large as possible, we want to lose bits as slowly as possible. Losing two or more alive bits in one step is strictly worse than losing only one, because each dead bit stops contributing immediately.
There are only bits, and after the first element we can kill at least one new alive bit per useful step. So the best possible sequence of prefix popcounts is
That gives maximum score
This upper bound is achievable: pick masks whose running AND loses exactly one bit each time.
Lexicographically smallest optimal permutation
Now we need the lexicographically smallest sacred permutation.
The first value is forced:
Suppose the currently alive bits form a mask alive. To stay optimal, the next number must kill exactly one alive bit. If it kills zero alive bits, we waste a position where the score could have dropped later incorrectly relative to the forced optimal shape; if it kills two or more alive bits, the score drops too fast. So during the first transitions, each next number must satisfy:
Among those valid unused choices, take the smallest to make the permutation lexicographically minimal.
What does that smallest choice look like?
Initially all bits are alive. To kill exactly one bit while making as small as possible, set the highest alive bit to and keep all lower alive bits as . Bits that are already dead do not matter for optimality, so to make smaller, set them to .
This gives the clean sequence:
Example for :
The running ANDs are exactly the same values, with popcounts
After the running AND becomes , every later prefix contributes . So the remaining unused numbers have no effect on . For lexicographic minimum, just append them in increasing order.
That is the whole construction:
Runtime is per test case, which is exactly the output size. Can't beat printing the damn answer.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
int m = 1 << n;
vector<int> ans;
vector<char> used(m, false);
for (int k = n; k >= 0; --k) {
int x = (1 << k) - 1;
ans.push_back(x);
used[x] = true;
}
for (int x = 0; x < m; ++x) {
if (!used[x]) ans.push_back(x);
}
for (int x : ans) cout << x << ' ';
cout << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
int m = 1 << n;
vector<int> ans;
vector<char> used(m, false);
for (int k = n; k >= 0; --k) {
int x = (1 << k) - 1;
ans.push_back(x);
used[x] = true;
}
for (int x = 0; x < m; ++x) {
if (!used[x]) ans.push_back(x);
}
for (int x : ans) cout << x << ' ';
cout << '\n';
}
return 0;
}