## Editorial for DMOPC '21 Contest 2 P5 - Permutations

Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.

Submitting an official solution before solving the problem yourself is a bannable offence.

Author: 4fecta

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.

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: 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: 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: 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: 