Editorial for COCI '13 Contest 6 #5 Hash
Submitting an official solution before solving the problem yourself is a bannable offence.
This requires a "meet-in-the-middle" attack: it's a common idea in crypto, but is also useful in a number of exponential-time competition problems. For , we can't consider all 
 words separately. However, we can consider 
 five-letter prefixes and 
 five-letter suffixes, and then figure out how to match them up. For each prefix, we can compute its hash, and store a table for how frequently each such hash occurs. For each suffix, we can compute what the hash of the prefix would need to be for the final hash to be 
, and then use the table to find the number of prefixes that match this suffix. To compute what the hash would need to be, we work backwards: assume the final hash is 
, and then remove one letter at a time from the end.
Let us observe an iteration of the stated hash function with the assumption that the current value of the hash is  and the ordinal number of the next letter is 
.
We will try to get the value of the previous state  when we know the current state 
 and the ordinal number of the letter which got us to the state 
.
Given the fact that we can look at the operation remainder when dividing with a power of two () as discarding any bits after the 
, it is easily noticed that the following holds:
Therefore,
because the bitwise XOR is inverse to itself and  will always be smaller than 
, this is also true:
The modular multiplicative inverse of  in the field of size 
 will exist if 
 and 
 are relatively prime. Since 
 is a power of two, this condition is true. The modular inverse can be obtained using extended Euclid's algorithm, fast exponentiation or with brute force because 
 is small enough.
Let us display the complete inverse relation of the hash function:
Having inverse relation in place, meet in the middle attack is done which gives us a time complexity of .
Comments