Official

C - Binary Strings Editorial by evima


Let us subtract \(1\) from \(X\) to consider it as \(0\)-based. Additionally, since every string on the blackboard begins with \(1\), let us assume that it does not exist. (For instance, we see 1 as an empty string.)

Let us gradually determine the string in question from the top.

There are \(2^{(N-1)}\) strings that begin with \(0\) or are empty. Thus, if \(2^{(N-1)} \leq X\), the answer begins with \(1\). On the other hand, if \(1 \leq X < 2^{(N-1)}\), the answer begins with \(0\). If \(X=0\), the answer is an empty string.

If \(1 \leq X < 2^{(N-1)}\), the rest of the answer can be found by solving the same problem after letting \(N:=N-1\) and \(X:=X-1\). Similarly, if \(2^{(N-1)} \leq X\), the rest of the answer can be found by solving the same problem after letting \(N:=N-1\) and \(X:=X-2^{(N-1)}\).

A naive implementation of this would involve \(O(N)\) operations on integers with \(O(N)\) digits, for a total of \(O(N^2)\) time.

However, by maintaining \(X\) in binary, we can execute the operations in a total of \(O(N)\) time.

First, when checking whether \(2^k \leq X\), it is enough to see whether the \(k\)-th bit is \(1\), since \(x < 2^{k+1}\) always holds.

Next, when letting \(X:=X-1\), we can just calculate it as if doing it on paper until there is no more borrowing, when we break the loop. Doing this \(N\) times makes \(ceil(N/2^k)\) loops reach the \(k\)-th digit (\(ceil(x)\) is the smallest integer not less than \(x\)). This is because once borrowing happens up to the \(k\)-th bit, every digit below it becomes \(1\), so the next borrowing up to the \(k\)-th bit will happen \(2^k\) operations later.

Since \(\sum_{0 \leq k \leq N-1} ceil(N/2^k)\) is \(O(N)\), it shows that the total complexity is \(O(N)\).

posted:
last update: