Editorial for DMOPC '21 Contest 2 P5 - Permutations
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
Consider the case where we must remove all edges from the tree. How many permutations can result from this? We should first note that the relative removal order of two edges which do not share an endpoint is irrelevant to the number of possible permutations. Next, note that the relative removal order of edges which share a common endpoint always matters and that there are
ways to remove them (where
is the number of edges incident to
), each of these producing a distinct permutation (trivially proven by induction). Combining this observation over all nodes in the graph, we see that the total number of possible permutations is
. We now use this knowledge to devise solutions of various complexities.
Subtask 1
For this subtask, we may simply brute force over all subsets of edges to be removed, using the formula derived above to calculate the number of possible permutations for each subset.
Time Complexity:
Subtask 2
For a better complexity, we should consider using dynamic programming on a tree, rooting the tree at node . Our state is
the number of permutations of the subtree rooted at
if we remove
edges in this subtree (including the edge leading to the parent of
), where
iff we remove our parent edge. However, we should also keep track of the number of removed edges incident to
in order to multiply by
later, so our transition should be computed with an auxiliary DP where
the number of permutations at node
if we remove
edges strictly in its subtree such that
of these connect
with a child of
. Implemented naively, this algorithm runs in
time.
Time Complexity:
Subtask 3
We should now strive to optimize our algorithm from before. One such optimization comes from looping up to only
when merging
with its parent, where
is the number of nodes in the subtree rooted at
. This actually optimizes our code to
, the proof of which is as follows:
Consider the set of nodes in our graph, initially with no edges. Each time we merge a node
with its parent, let's add an edge from all
nodes in the subtree of
to every other node in the subtree of any previously processed child of
's parent. Each edge represents a merge that we must process. In the end, the graph will become a complete graph with
edges, so we will be processing
merges in total. Since each merge is processed in
, our proof is complete.
This technique can be applied to various other tree DP problems in order to optimize the complexity by a factor of .
Time Complexity:
Subtask 4
You may have realized that the modulus is quite unusual. Why is that? Well, using any computational device at hand, we find that the prime factorization of
is
. This implies that
for any
, which is actually highly useful for this particular problem. Specifically, this means that the
dimension in our auxiliary DP only needs to go up to
; any higher and the product
would just be congruent to
, so there's no point in keeping track of it at all! Thus, our merges can now be processed in a constant amount of time instead of
, bringing the total complexity down to
.
Time Complexity:
Comments