1. 程式人生 > >luoguP3830 [SHOI2012]隨機樹 期望概率 + 動態規劃 + 結論

luoguP3830 [SHOI2012]隨機樹 期望概率 + 動態規劃 + 結論

str src ans col inf name ret 節點 include

技術分享圖片

技術分享圖片

題意非常的復雜,考慮轉化一下:

每次選擇一個葉節點,刪除本葉節點(深度為$dep$)的同時,加入兩個深度為$dep + 1$的葉節點,重復$n$輪

首先考慮第$1$問,(你看我這種人相信數據絕對是最大的數據,直接$f[i][S]$表示$i$個葉子結點,深度之和為$j$的時候的概率,然後化前綴和化出來...)

對於一個深度為$x$的點,對它操作後,深度增加了$2 * (x+ 1) - x = x +2$

現在考慮平均的情況,令$f[i]$表示$i$個節點的平均深度,那麽$f[i] = \frac{f[i - 1] *(i - 1) + f[i - 1] + 2}{i} = f[i - 1] + \frac{2}{i}$

其中,$f[i - 1] * (i - 1)$表示原來的總深度,$ / i$表示新的平均個數

邊界為$f[1] = 0$(註意題目中深度的定義)

接著是第$2$問,考慮求解$f[i][j]$表示$i$個葉節點的樹,深度為$j$的概率

那麽$E(X) = \sum\limits_{i = 0}^n i * f[n][i]$

只要考慮怎麽轉移,自然地想到全概率公式,有

$f[i][j] = \sum\limits_{L = 1}^{i - 1} p[i][L] \sum\limits_{x = 1}^j \sum\limits_{y = 1}^j f[L][x] * f[i - L][y](x = j - 1 || y = j - 1)$

其中,$p[i][L]$表示$i$個葉子結點的樹,有$L$個葉子結點落在左邊的概率

同時, 註意右子樹至少有$1$個葉子結點

那麽,這是一個$O(n^4)$的算法

考慮進行優化,令$g[i][j] = \sum\limits_{i = 1}^j f[i][j]$

那麽,現在我們的轉移式變為了$f[i][j] = \sum\limits_{L = 1}^{i - 1} p[i][L] * (2 *f[L][j - 1] * g[i - L][j - 1] - f[L][j - 1] * f[i - L][j - 1])$

現在,只要求出$p[i][L]$,我們就得到了一個$O(n ^ 3)$的算法

而我們可以使用數學歸納法證明(不難)

$p[i][L] = \frac{1}{i - 1} (1 \leq L \leq i - 1)$

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define ri register int
#define de double
#define sid 105

int q, n;
de ans, f[sid][sid], g[sid][sid];

int main() {
    cin >> q >> n;
    if(q == 1) {
        for(ri i = 2; i <= n; i ++) ans += 2.0 / i;
        printf("%lf\n", ans);
    }
    else {
        f[1][0] = 1;
        for(ri i = 0; i <= n; i ++) g[1][i] = f[1][0];
        for(ri i = 2; i <= n; i ++) {
            for(ri s = 0; s < i; s ++)
            for(ri L = 1; L < i; L ++)
            f[i][s + 1] += (2 * f[L][s] * g[i - L][s] - f[L][s] * f[i - L][s]) / (i - 1);
            g[i][0] = f[i][0];
            for(ri s = 1; s <= n; s ++) g[i][s] = g[i][s - 1] + f[i][s];
        }
        for(ri i = 1; i <= n; i ++) ans += i * f[n][i];
        printf("%lf\n", ans);
    }
    return 0;
}

實際上,由於是對$E[X] = \sum\limits_{i = 1}^n i *P(X = i)$進行計數

因此,我們可以把$P(x = i)$拆成$i$份

那麽,對$E[X] = \sum\limits_{i = 1}^n P(X \geq i)$計數也是可以的

然而本質沒有什麽改變...

luoguP3830 [SHOI2012]隨機樹 期望概率 + 動態規劃 + 結論