Editorial for Wesley's Anger Contest 5 Problem 5 - A Squirrel's Life
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
Subtask 1
For subtask 1, we can generate all possible sequences starting from and ending at , and then count the number of valid sequences in linear time.
Time Complexity: The time complexity is . Note that while that may seem unreasonable to fit within the time limit, two of the events in the sequence have already been set.
Subtask 2
For subtask 2, we can tackle this problem using dynamic programming. The state can be modelled using the current node, the length of the current sequence, a boolean marking whether or not event has been reached, and another boolean marking whether or not event has been reached.
Alternatively, this can be tackled using matrix exponentiation. If we analyze the transition of the dynamic programming solution it shares similarities with raising the adjacency matrix to the power of . Using the exponentiation by squaring trick we can first build the adjacency matrix with nodes (the nodes have been encoded with the two booleans to mark whether or not the events of type or have been visited yet), and then raise it to the power of .
Time Complexity: For the dynamic programming solution, the time complexity is with a large hidden constant. For the matrix exponentiation solution, the time complexity is with a large hidden constant.
Subtask 3
Subtask 3 is an extension of subtask 2. For the dynamic programming solution, one more parameter to describe the number of supplies found is required. For the matrix exponentiation solution, we need to build a graph with nodes to encode the number of acorn supplies found into the graph.
Time Complexity: For the dynamic programming solution, the time complexity is with a large hidden constant. For the matrix exponentiation solution, the time complexity is with a large hidden constant.
Subtasks 4 and 5
These subtasks are meant to reward contestants who attempted to optimize their solution from subtask 3. The following subtasks' main objective is to reduce the constants. This can be done by reducing the number of nodes in the graph or by optimizing the matrix multiplication itself.
The first optimization that can be done is to take out the constant in the number of nodes in the graph. We can do this using inclusion-exclusion. Let return the number of walks from node to node using the graph . To retrieve all the walks where both events and are visited, the answer is , where is the graph obtained after deleting the node . In practice, this saves a constant of around .
The second optimization comes from the observation that a lot of the entries in the matrix will always be equal to . This is because you can never decrease your supply of acorns throughout the walk. For example, a node encoded with an acorn supply of 3 can never reach a node with a supply of any integer less than 3. We can set up the matrix multiplication's loops efficiently to save a constant of around to in practice.
The third optimization comes from the observation that only needs to return the number of walks from node to node . The final matrix does not need to be an entire matrix, and we only need to keep the first row. This reduces the matrix into a vector, which we can do much more efficient vector-matrix multiplication instead. In practice, this saves a constant of around .
Time Complexity: with a smaller hidden constant.
Subtask 6
For the full solution, all three optimizations should be used to pass within the time limit. A proper implementation should be able to pass with ease and will be left as an exercise.
Note that there is an alternate solution which uses Berlekamp-Massey to find the shortest linear recurrence relation for a sequence. The sequence can be determined using the dynamic programming solution from subtasks 2 and 3.
Time Complexity: with a very small hidden constant.
Comments