Editorial for COCI '19 Contest 2 #4 Popcount


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Esoteric programming language, only one variable, constraints on source code length, looks like a perfect combination for solving "subtask by subtask".

In the first subtask, we're allowed to use the number of commands that is (almost) the same as the number of bits of the input value. This suggests that we could solve the subtask "bit by bit". Let's assume that we have successfully solved the suffix of X bits, i.e., that suffix of A now contains the number of ones in the corresponding suffix of input value while the other bits of A remain unchanged with regards to the input value. Note that the input value itself already has a solved suffix of size 1. Suffix of size X+1 bits will be solved by adding the value of bit X+1 to the variable A while also setting that bit to 0. We can do that using the following command A=((A&(((1<<N)-1)-(1<<X)))+((A&(1<<X))>>X)). We could have solved the first subtask by using N-1 commands of this form.

To solve the second subtask, we can use the same idea from the first subtask along with the fact that variable A can be found at most 5 times in the right side of the command. Therefore, instead of solving the task "bit by bit", we will solve it using the technique "four bits by four bits". This will reduce the number of used commands 4 times.

To solve the remaining subtask, we could use an idea from the famous data structure, the segment tree. Let's imagine that we have built a segment tree on top of our N bit number. Each node of the tree will store the sum of bits (number of ones) in its subtree. Imagine also that those values are written in binary with the number of bits that corresponds to the length of the interval (segment) which is covered by that node.

If we were to glue the values of all leaves (from left to right) in our segment tree, we would get the input value into our program. If we glue the values of their parents in the same way, we will get the wanted value of number A after our first command. If we were to repeat this process until the root, we will in the end store the correct value in variable A by using an order of \mathcal O(\log N) commands, which should be enough for the last two subtasks. The only thing left to do is to find the command which makes the transition from one set of nodes to their parents in the segment tree.

For the first command, we could have taken all bits at even indices and add to them all bits at odd indices shifted to the right by one. We can do that with the expression ((...01010101&A)+((...10101010&A)>>1)). In the next step (intervals of length 4) the expression could be ((...00110011&A)+((...11001100&A)>>2)). By repeating this pattern, we will solve the task using \mathcal O(\log N) commands, each of which has two occurrences of A in them.

In this task, for the sake of implementation, we suggest using Python or Java.


Comments

There are no comments at the moment.