AtCoder - Subtree
Authors: Benjamin Qi, Andi Qu
Solving for One Root
Let's consider a simpler problem - assuming that node 1 is painted black, how many ways can we paint the tree?
First, root the tree at node 1.
Let be the number of ways that we can paint the subtree of node if we know that node is painted black. (1 if node is a leaf)
For each child of , there are ways to paint its subtree if is painted black.
This means that we have the recurrence
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 excluding node from the graph and we know that node is painted black. (1 if node is the root)
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
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 .
Code
down
corresponds to and up
corresponds to .
/*** Description: modular arithmetic operations*/template<int MOD, int RT> struct mint {static const int mod = MOD;static constexpr mint rt() { return RT; } // primitive root for FFTint v; explicit operator int() const { return v; } // explicit -> don't silently convert to intmint() { v = 0; }mint(ll _v) { v = (-MOD < _v && _v < MOD) ? _v : _v % MOD;