D - Least Unbalanced Editorial by en_translator
Conclusion firsts: the answer can be obtained by the algorithm described by the following C++ snippet:
vector<int> ans{K};
for (int n = 0; n < N; n++) {
vector<int> nxt;
for (int a : ans) {
nxt.push_back(a / 2);
nxt.push_back(a - a / 2);
}
ans = nxt;
}
(Proof) We consider the cases where \(K\) is divisible by \(2^N\) and where it is not.
1. When \(K\) is divisible by \(2^N\)
If \(K\) is divisible by \(2^N\), then we can set \(B\) to the sequence containing \(2^N\) copies of \(\frac{K}{2^N}\). Its imbalance is \(0\), which is minimum possible. One can assert that the algorithm above yields a sequence containing \(2^N\) copies of \(\frac{K}{2^N}\), so the algorithm is valid.
2. When \(K\) is not divisible by \(2^N\)
When \(K\) is not divisible by \(2^N\), then we cannot achieve an imbalance \(0\). That is, the imbalance is at least \(1\).
Conversely, one can prove that the algorithm above achieves an imbalance \(1\).
The proof is outlined as follows. In the algorithm above, the length of the sequence is doubled step-by-step: \(1, 2, \dots, 2^N\). This is the inverse procedure of that in the problem statement. In other words, the imbalance of the obtained sequence is the maximum difference between the maximum and minimum values of the elements in the ans
assigned at any time in the procedure.
As a lemma, one can prove that the difference between the maximum and minimum values contained in ans
is always \(1\) or less.
This lemma can be proved as follows. The case where the difference between the maximum and minimum values contained in ans
is \(1\) or less always falls into one of the following three cases. The initial state satisfies A.
- A: (maximum value) = (minimum value).
- B: For some integer \(m\), (maximum value) \(= 2m+1\) and (minimum value) \(= 2m\).
- B: For some integer \(m\), (maximum value) \(= 2m\) and (minimum value) \(= 2m-1\).
Then one can prove that when you apply an operation to any of the states A, B, or C, the resulting state also satisfy one of A, B, and C. (We omit the proof here, but it can be shown with a casework. Notice that obtaining a / 2
and a - a / 2
from a
is equivalent to finding \(\lfloor a/2 \rfloor\) and \(\lceil a/2 \rceil\) from \(a\).) Therefore, the lemma has been proved.
Hence, the imbalance of the sequence obtained by the procedure above is \(1\), which is what we want.
The complexity is \(\mathrm{O}(2^N)\), which is fast enough.
- Sample code (C++)
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main() {
int N, K;
cin >> N >> K;
vector<int> ans{K};
for (int n = 0; n < N; n++) {
vector<int> nxt;
for (int a : ans) {
nxt.push_back(a / 2);
nxt.push_back(a - a / 2);
}
ans = nxt;
}
int max = *max_element(begin(ans), end(ans));
int min = *min_element(begin(ans), end(ans));
cout << max - min << "\n";
for (int i = 0; i < (int)ans.size(); i++) {
cout << ans[i] << " \n"[i + 1 == (int)ans.size()];
}
}
posted:
last update: