問題は本当に少し嫌です。
ANS [i]はiがサブツリーのルート、すべての有効な逆配置の、すなわち数に対する回答を表します。
ウェイ[i]はiのルートに有効に配置されている数を表します。
DP [I] [J] [k]は、iの数は、k番目のノードj正規配列のすべての法的構成のルートで表します。
そして、3つのDP配列は答えを更新します。
特定の参照https://blog.csdn.net/ShinFeb/article/details/52212775
#pragma GCC最適化(2) の#pragma GCCの最適化(3) の#include <ビット/ STDC ++。H> に#define LL長い長 の#define LD長い二重 の#defineは、符号なしの長い長いULL の#define最初Fiが の#define SE第二 の#define MKをmake_pair の#define PLL対<LL、LL> の#define PLI対<LL、整数> の#define PII対<整数、整数> の#define SZ(X)((INT)x.size()) の#define ALL(X) (X).begin()、(X).END() の#define FIO IOS :: sync_with_stdio(偽)。cin.tie(0)。使用して名前空間はstdを、 CONSTの INT N = 3E5 + 7 。 const int型 INF = 0x3f3f3f3f 。 constの LL INF = 0x3f3f3f3f3f3f3f3f 。 CONST INT MOD =(INT)1E9 + 7 。 constの ダブル EPS = 1E- 8 ; CONST ダブル PI = ACOS( - 1 )。 テンプレート < クラス T、クラス S>インラインボイド追加(T&、S b)は{A + B =。もし(> = MOD)A - = MOD;} テンプレート < クラスT、クラス S>インラインボイドサブ(T&、S b)は、{ - = B。もし(< 0)、A + = MOD;} テンプレート < クラス T、クラス S>インラインBOOL chkmax(T&、S B)は{ 返す <bは?= B、真:偽;} テンプレート < クラス T、クラス S>インラインブール chkmin(T&、S b)は{ 返す > bは?A = B、真:偽;} int型N、根; int型の ANS [ 51]、方法[ 51 ]、SZ [ 51 ]。 INT DP [ 51 ] [ 51 ] [ 51 ]。 INT TMP [ 51 ] [ 51 ]。 INT和[ 51 ] [ 51 ]。 INT C [ 101 ] [ 101 ]。 ベクター < INT > G [N]。 ボイド DFSは(int型、UをINT {FA) のために(int型 i = 0 ; iは<SZ(G [U])iは++ ){ 場合(G [U] [I] ==FA){ G [U] .erase(G [U] .begin() + I)。 } } ANS [U] = 0 ; SZ [U] = 1 。 用(オート&V:G [U]){ DFS(V、U)。 SZ [U] + = SZ [V]。 } のために(int型 I = 1は iが++; iがn = < {) のために(int型の J = 1 ; J <= nであり、j ++ ){ DP [U] [I] [J] = 0 ; 和[i] [j]は = 0 。 } } 方法[U] = 1 。 int型 cur_cnt = 0 ; 用(オート&V:G [U]){ int型 nex_cnt = cur_cnt + SZ [V]。 ANS [U] = 1LL * C [nex_cnt] [cur_cnt] * ANS [U]%のMOD *方法[V]%MOD。 (ANS [U]、1LL追加 * C [nex_cnt] [cur_cnt] * ANS [V]%MOD *方法[U]%のMOD)。 以下のために(int型 i = 1 ; iが<= N; iは++ ){ ための(int型のk = 1 ; K <= SZ [V]; kは++ ){ 場合(!DP [V] [I] [K])続け; 用(INT J = 0 ; J <= cur_cntあり、j ++ ){ int型 A = 1LL * C [K + J - 1 ] [J] * C [cur_cnt - J + SZ [V] - K] [cur_cnt - J] %モッズ; INT B =(SUM [I] [cur_cnt] -和[I] [J] + MOD)%MOD。 INT C =(和[n]は[J] -和[I] [J] + MOD)%MOD。 追加(ANS [U]、1LL * DP [V] [I] [K] *%のMOD×(B + C)%のMOD)。 } } } のための(int型 i = 1 ; iが<= N; I ++){ ための(int型 J = 1 ; J <= nであり、j ++ ){ TMP [I] [J] = 0 ; } } のために(int型 I = 1は iが++; iがn = < {) のために(int型の J = 1 ; J <= nex_cntあり、j ++ ){ ための(int型のk = 1 ; K <= Jあり、k ++ ){ int型、A = 1LL * C [J - 1 ] [K - 1 ] * C [cur_cnt + SZ [V] - J] [cur_cnt - K]%モッズ; INT B = 1LL * C [J - 1 ] [K - 1 ] * C [cur_cnt + SZ [V] - J] [SZ [V] - K]%MOD。 (TMP [I]、[J]、1LL追加 *の方法[V]%MOD * DP [U] [I] [K]%のMOD)を、 追加(TMP [I]、[J]、1LLの a * b *表方法[U]%のMOD * DP [V] [I] [K]%のMOD)。 } } } のための(int型 i = 1 ; iが<= N iが++ ){ ため(INT J = 1 ; J <= nであり、j ++ ){ DP [U] [I] [J] = TMP [I] [J ]; 和[I] [j]は = DPを[U] [I]、[J]。 (和[I]、[J]、和[I追加 - 1 ] [J])。 (和[I]、[J]、和[I] [J追加 - 1 ])。 サブ(SUM [I]、[J]、和[I - 1 ] [J - 1 ])。 } } 方法[U] = 1LL *方法[U] *方法[V]%MOD * C [nex_cnt] [cur_cnt]%MOD。 cur_cnt = nex_cnt。 } DP [U] [U] [SZ [U] = 道[U]。 追加(ANS [U]、合計[N] [cur_cnt])。 サブ(ANS [U]、和[U] [cur_cnt])。 } のボイドINIT(){ ため(int型 i = 1 ; iが<= N iが++ ){ G [i]が.clear(); } } int型のmain(){ ため(int型 i = 0 ; iが<= 100 ; I ++ ){ ための(int型 J = C [i]が[ 0 ] = 1 ; J <= I; J ++ ){ C [i]は[ J] = C [I - 1 ] [J - 1 ] + C [I - 1 ] [J]。 もし(C [I] [J]> = MOD)C [I] [J] - = MOD。 } } 一方、(scanf関数(" %d個の%のD "!、&N、&ルート)= EOF){ INIT()。 以下のために(int型 i = 1 ; iがn <; iは++ ){ int型Uを、V。 scanf関数(" %d個の%d個"、&U&V); G [U] .push_back(V)。 G [V] .push_back(U)。 } DFS(ルート、0 ); printf(" %d個の\ n " 、ANS [ルート])。 } 戻り 0 。 } / * * /