1. 程式人生 > >[BZOJ3167][Heoi2013]Sao(樹形DP+組合數學)

[BZOJ3167][Heoi2013]Sao(樹形DP+組合數學)

Address

洛谷P4099
BZOJ3167

Solution

定義狀態: f [ u ] [ i ] f[u][i]

表示 u u 的子樹內所有的點進行排列, u u 排在位置 i
i
的方案數。
考慮按照樹形揹包的方式轉移,設 f [ u ] f'[u]
為列舉到 u u 的子節點 v v 之前的 DP 陣列。
如何合併 f [ u ] f'[u] f [ v ] f[v] 呢?
先考慮 u u 必須排在 v v 後面的情況:
先列舉 i i j j ,考慮如何從 f [ u ] [ i ] f'[u][i] f [ v ] [ ] f[v][] 合併到 f [ u ] [ i + j ] f[u][i+j]
(上面的 i i 表示列舉到 u u 的子節點 v v 之前子樹中 u u 的排名, j j 表示 v v 的子樹內排名在 u u 前面的點數)。
而如果 u u 必須排在 v v 的後面,這就要求了能參與轉移的 f [ v ] [ k ] f[v][k] 必須滿足 k j k\le j
u u 的子節點 v v 之前子樹大小為 s u s'_u v v 的子樹大小為 s v s_v ,如何求把 f [ u ] [ i ] f'[u][i] f [ v ] [ k ] f[v][k] k j k\le j )合併起來的方案數呢?
這等價於把兩個長度分別為 s u s'_u s v s_v 的序列合併成一個序列,使得新序列任意兩個相同元素在原序列中的相對位置不變,並且對於 x x x x 為新序列中第 i i 個來自序列 s u s'_u 的元素),必須滿足 1 1 x x 中恰好有 j j 個元素來自序列 s v s_v
這又等價於把 s v s_v 個元素切割成 s u + 1 s'_u+1 塊(塊內可以為空),滿足前 i i 塊裡恰好有 j j 個元素。
根據組合數學的知識得到這樣的方案數為:
C i + j 1 i 1 × C s u i + s v j s u i C_{i+j-1}^{i-1}\times C_{s'_u-i+s_v-j}^{s'_u-i}
所以轉移:
f [ u ] [ i + j ] + = C i + j 1 i 1 × C s u i + s v j s u i × f [ u ] [ i ] × k j f [ v ] [ k ] f[u][i+j]+=C_{i+j-1}^{i-1}\times C_{s'_u-i+s_v-j}^{s'_u-i}\times f'[u][i]\times \sum_{k\le j}f[v][k]
u u 排在 v v 之前時:
f [ u ] [ i + j ] + = C i + j 1 i 1 × C s u i + s v j s u i × f [ u ] [ i ] × k j f [ v ] [ k ] f[u][i+j]+=C_{i+j-1}^{i-1}\times C_{s'_u-i+s_v-j}^{s'_u-i}\times f'[u][i]\times \sum_{k\ge j}f[v][k]