AtCoder DP Contest - Subtree
Authors: Benjamin Qi, Andi Qu
Solving For One Root
Let's consider a simpler problem:
Assuming that node is painted black, how many ways can we paint the tree?
First, root the tree at node . Let be the number of ways that we can paint the subtree of node such that either node is colored black, or no nodes are colored black. Note that if is a leaf, then (we choose to color node black or not).
For each child of , there are ways to paint its subtree if is painted black. This means that we have the recurrence
where the product corresponds to painting node black and the corresponds to painting node white.
The answer to the simpler problem is thus . Finding all takes time.
Solving For All Roots
First, root the tree arbitrarily and do a DFS to find all .
Let be the number of ways to colour the tree if we remove node 's subtree such that either the parent of is black, or no nodes are colored black. Note that .
The number of ways to paint the tree if we know node is black is simply . How can we find efficiently though?
The basic recurrence for computing is
where the product corresponds to painting the parent of black and the corresponds to painting the parent of white.
Since isn't guaranteed to be prime though, we can't just find the product of each node's children and divide that product by each of its children's (since we can't find modular inverses easily).
However, notice how if node is the -th child of its parent, then we can use prefix and suffix products to compute
without using division. (i.e. We find the product of for the first to the -th child of 's parent, the product of for the -th to the last child of 's parent, and then multiply those together.)
Finding all takes time using a DFS, so the total complexity of this algorithm is thus .
Implementation
down
corresponds to and up
corresponds to . The code uses the
exact same recurrences mentioned above.
Code Snippet: Benq Template (Click to expand)/*** Description: modular arithmetic operations*/template <int RT> struct mint {// static const int mod = MOD;static constexpr mint rt() { return RT; } // primitive root for FFTint v;
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!