Editorial for IOI '16 P5 - Unscrambling a Messy Bug
Submitting an official solution before solving the problem yourself is a bannable offence.
Subtask 1 allows you to check all possible elements, so it can be solved by various solutions. For example, you can add
random elements in your set, check all elements, try all
transpositions and check that it will give you the same result.
Subtask 2 may be solved by a simple solution, using at most
add_element
operations and at most
check_element
operations.
- Let's add
elements into the set,
element will have first
bits set to one.
add_element("10000000")
add_element("11000000")
add_element("11100000")
add_element("11110000")
add_element("11111000")
add_element("11111100")
add_element("11111110")
add_element("11111111")
- Now we will get positions of bits one by one. First, let's find the position of bit
. This can be done using at most
queries:
check_element("10000000") returned false
check_element("01000000") returned false
check_element("00100000") returned false
check_element("00010000") returned false
check_element("00001000") returned false
check_element("00000100") returned true
- Now we know the position of bit
and want to find the position of bit
. This can be done using at most
queries:
check_element("10000100") returned false
check_element("01000100") returned false
check_element("00100100") returned false
check_element("00010100") returned true
- And so on, we can find position of
bit using
queries, so the total number of queries in the worst case is
.
Subtask 3 can be solved by several optimizations of the previous algorithm. The simplest one is to shuffle the order of bytes. This will give us the average number of queries , which was enough to pass the tests.
Subtasks 4 and 5 require an solution, in subtask 4 you can make at most
operations of each type, in subtask 5 you can make only
operations.
Subtask 5 may be solved using divide and conquer technique. Let's try to split all bits into two halves using requests, and solve the problem for each half independently. In this solution, we will make at most
operations of each type.
- To split a group of bits into two halves, we will add into set
elements,
element will have
bit set to one, all other set to zero:
add_element("10000000")
add_element("01000000")
add_element("00100000")
add_element("00010000")
- After this, we will check
elements with a single bit set to one. For example:
check_element("10000000") returned false
check_element("01000000") returned true
check_element("00100000") returned false
check_element("00010000") returned false
check_element("00001000") returned true
check_element("00000100") returned true
check_element("00000010") returned false
check_element("00000001") returned true
Now we know which
bits correspond to the first
bits. In this example, we know that bits
,
,
, and
correspond to bits
–
. So now we will solve the same problem for them only, and after that solve the problem for other
bits.
In order to solve the problem for some subset of bits, we need to make sure that the elements we use in different subproblems are distinct. We can achieve this by setting all bits that are not in our subset to ones. For example, when we want to split bits
–
into halves, we will make the following operations.
add_element("10001111")
add_element("01001111")
check_element("11110010")
check_element("10111010")
check_element("10110110")
check_element("10110011")
Comments