Editorial for Wesley's Anger Contest 4 Problem 4 - The Almighty Acorn
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
Subtask 1
For subtask 1, we can simulate the process of creating the infinite string. This can be done by concatenating the first numbers together and then using a standard substring finding function. We can observe that any string of length can be found within the first positive integers. This applies to strings with leading zeroes as well, since we can use the nonzero digits at the end of the string to create a new valid number. For example, the string 008
can be found in the concatenation of and .
The edge case to watch out for is the string 000
, which appears with the number .
Time Complexity: to create the string from to , and to find its leftmost occurrence using naive string search.
Subtask 2
For subtask 2, we can build on the idea of "creating" a valid number. Since smaller numbers appear earlier in the infinite string, the problem then becomes finding the smallest valid number that when concatenated with its successors, contains as a substring.
To generate a potentially valid number, we can loop for its size in increasing order, and then loop for the possible offset positions of this valid number. To check if this generated number can form , we can simulate the addition by and concatenate it with the first number until the new string's length exceeds . Comparing the two strings in linear time will suffice for this subtask.
Using the smallest valid number, we can determine its position in the infinite string. If the number has more than digits, then there are at least digits preceding it. If is the smallest valid number, is the number of digits in , and is the offset, then the index can be defined as:
Note that while BigInteger libraries can help with some of these steps, it does not bring the complexity down and does not make this subtask simpler to implement.
Time Complexity: Since we have a loop for the length, a loop for the offset, and an string check, the total time complexity is .
Subtask 3
For the full solution, let's improve the string check. There are a few possible approaches such as using a suffix array, but the method that will be described here will use hashing.
Instead of building the concatenation, we can check on itself. For a valid string, there should be a chain of non-overlapping substrings that always increase by from left to right. For a chain of size , there will be non-overlapping substrings. We can compare adjacent substrings to check for the validity.
To perform a comparison, let's define two hashing functions:
, which hashes the substring ,
, which hashes the substring .
To check if two adjacent substrings have a difference of , we can use and compare it with the hash value of the adjacent substring using .
Calculating is straightforward and can be done in constant time. This will not be further explained as there are other string problems which use this technique such as this problem.
Calculating is trickier and requires a few observations. First, hash values will only increase by if the string's last digit is not a . Second, the trailing s will all become when incremented, and increase the rightmost digit that is not a . We can precompute the number of trailing s that end at each specific position in and use it to adjust the hash value accordingly. A proper implementation should be able to calculate in constant time as well.
How much does this bring the complexity down? With comparisons for the string check, the time complexity can be modelled as:
Careful implementation must be done to avoid edge cases and will be left as an exercise for the reader.
Time Complexity:
Comments