Editorial for Baltic OI '07 P5 - Connected Points
Submitting an official solution before solving the problem yourself is a bannable offence.
Firstly, if you try to draw a polygon fulfilling the necessary conditions, you are strongly limited in the ways you can move. When starting from the lower left point of the grid in an anti-clockwise direction, you have to get to the lower right point first before you can move to any point in the top line of the grid. This is due to the fact that your polygon would otherwise split the grid in two parts, although you still had to get to the lower right and to the upper left point. Since this is impossible, we can deduce that there is a bottom part of the polygon never connecting points in the top line of the grid and a top part of the polygon never connecting points in the bottom line in the grid.
Figure 1: Dashed line: Bottom part. Pointed line: Top part.
Secondly, that means that when drawing the top or the bottom part of the polygon from left to right, only two lines of the grid may be used which means you cannot move more than one column in the opposite direction. Otherwise the way to the rightmost column could not be completed.
With these observations, we can take advantage of a left-right-ordering: We cut a valid polygon at a specified column vertically in two parts and look at the left part of it. There will be two open endings (first observation) at which we could continue to draw the polygon. Apart from the last column the shape of the left part of the polygon does not influence the number of ways we can continue to draw it, since it is not possible to go more than one column backwards (second observation).
Now we have to identify the situations or states that occur at the specified column where we made our vertical cut. With each state we associate how many possibilities we had to draw the left part of the polygon. When we find a recursive formula to get from the states of column to the states of column we can construct all possibilities from left to right, and we have basically solved the problem.
The states you choose to identify are arbitrary, as long as they are correct. A very short solution is to discard any vertical connections in the column we look at, and to associate with the upper, the middle and the lower point of the column how many connections they have to the column to the left.
State 1 | State 2 | State 3 | State 4 | State 5 | State 6 |
---|---|---|---|---|---|
One example for each state is shown in fig. 2. If we are in column we do not need any other information than what state the left part of the polygon is in and how many possibilities we had to draw it so far. Let us denote that number with .
Figure 2: Examples for states , , , , and .
Now we have to find the recurrence relationship for our :
In fig. 3, all possibilities to construct state out of the column to the left are being shown.
Figure 3: Recurrence relationships for state .
Let us now take a look at the possible starts, i.e. possible connections between the top and bottom part of the polygon.
Figure 4: Possible starting configurations are states (twice) and states , and .
Obviously states and as well as states , and have the same recurrence relationships, and their starting values are equal, too. Therefore, it suffices to calculate states , and :
In column we have to close our polygon. Then the final result is , i.e. . See fig. 5 for reference.
Figure 5: Possible closing configurations are states , and .
Since the state change from column to is a linear mapping, we can do it with a matrix multiplication. In order to do that, we combine states , and in a vector with three components, and rewrite the recurrence relationships above as a matrix:
Now, the problem is being solved by calculating the expression .
We could simply do matrix-vector multiplications to get the result, but this is definitely too slow for . As these multiplications are associative, we can instead calculate . This can be done rather quickly, namely in steps:
calculateMpowerE(M, e):
Result := IdentityMatrix;
while (e > 0):
if (e mod 2 == 1)
Result = Result * M;
M = M * M;
e = e div 2;
return Result;
Some math or a different state representation allows you to reduce the matrix to a matrix but this was not expected.
The last problem we have is that the numbers can get really big. Since only the number of possibilities modulo needs to be calculated, we can do this modulo-operation on all intermediate results. They will always fit in a 64-bit integer, so there is no more trouble in that respect.
A different solution to get full score is to use a linear approach but precompute values for multiples of and start the search from there.
Comments