HDU - 5789順列のDP(説明を参照)

5789 - HDU

問題は本当に少し嫌です。

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 
} 

/ * 
* /

 

おすすめ

転載: www.cnblogs.com/CJLHY/p/11502975.html