Ultraviolet A 1436-Counting heaps
Question Link
Given the structure of a tree, place 1-N numbers in it. The value of the parent node must be smaller than that of the child node.
Train of Thought: f [u] indicates the case where u is the subtree, then the subtree is f (v1), f (v2), f (v3 )... f (vn ). to form a subtree is equivalent to selecting s (v1), s (v2), s (v3 )... s (vn ). f (v1) f (v2 )... f (vn) (s (u)-1 )! \ (S (v1 )! S (v2 )! ... * S (vn )!) The formula is obtained after simplification:
F (u) = (s (root)-1 )! /S (1) s (2) s (3)... s (n)
Because the answer is very big to m, but m is not a prime number, you cannot directly find the inverse, you can only split the denominator of the numerator into the prime factor, and finally get the de-modulo in the form of molecules.
Code:
# Include
# Include
# Include
Using namespace std; const int N = 500005; int t, n, cnt [N], prime [N], vis [N], pn = 0, f [N], ispri [N]; long m; int bfs () {// use dfs to REqueue
Q; for (int I = 1; I <= n; I ++) if (! Vis [I]) Q. push (I); while (! Q. empty () {int now = Q. front (); Q. pop (); if (now = 0) break; cnt [f [now] + = cnt [now]; vis [f [now] --; if (vis [f [now] = 0) Q. push (f [now]) ;}} void solve (int num, int v) {for (int I = 0; I <pn & prime [I] <= num; I ++) {while (num % prime [I] = 0) {cnt [prime [I] + = v; num/= prime [I];} if (ispri [num]) {// without this pruning, it is inevitable that TLE cnt [num] + = v; break ;}} long pow_mod (long x, int k) {long ans = 1; while (k) {if (k & 1) ans = ans * x % m; x = x * x % m; k> = 1;} return ans;} int main () {for (int I = 2; I <N; I ++) {if (vis [I]) continue; ispri [I] = 1; prime [pn ++] = I; for (int j = I; j <N; j + = I) vis [j] = 1;} scanf ("% d", & t); while (t --) {scanf ("% d % lld", & n, & m); for (int I = 1; I <= n; I ++) cnt [I] = 1; f [1] = 0; memset (vis, 0, sizeof (vis); for (int I = 2; I <= n; I ++) {scanf ("% d", & f [I]); vis [f [I] ++;} bfs (); memset (vis, 0, sizeof (vis); for (int I = 1; I <= n; I ++) vis [cnt [I] ++; memset (cnt, 0, sizeof (cnt); for (int I = 2; I <= n; I ++) {solve (I, 1); if (vis [I]) solve (I,-vis [I]);} long ans = 1; for (int I = 0; I <pn; I ++) {if (cnt [prime [I] = 0) continue; ans = (ans * pow_mod (long) prime [I], cnt [prime [I]) % m;} printf ("% lld \ n ", ans);} return 0 ;}