題意

給定一個長度為 NN 的序列 X0,X1,X2,⋯ ,XN−1X_0, X_1, X_2, \cdots, X_{N-1},f(X)f(X) 定義如下:

對於所有有 NN 個節點的樹,滿足第 ii 個節點的度數為 XiX_i,f(X)f(X) 及為所有這樣樹的直徑的最大值。

給定一個 NN,求所有長度為 NN 的序列 XX 的 f(X)f(X) 之和。

由於有多組詢問,單次詢問時間複雜度必須小於 O(log⁡N)O(\log N)。

解法

首先,一棵有 NN 個節點的樹有 N−1N-1 條邊,故 ∑X=2(N−1)\sum X = 2(N - 1),且 min⁡X≥1\min{X} \ge 1。

考慮如何從 XX 求出 f(X)f(X)。先從鏈的情況考慮,這時有 XX 由兩個 11 和 n−2n - 2 個 22 組成,且 f(X)=n−1f(X) = n - 1。對於其他 XX,可以理解成一些 22 變成了 11,並且把多餘的 11 加到了其他非 11 的地方,反映到圖上就是原來的鏈中的一些度為 22 的節點被刪除,又重新連到了其他原來非 11 的節點上,變成了葉子。自然,每多一個 11,直徑就小 11,故設序列 AA 中 11 有 ii 個,則 f(X)=n−i+1f(X) = n - i + 1。(有點抽象,自己畫圖理解)

故列舉 ii,11 的個數為 ii 的答案為 (n−i+1)×(ni)×(i−2+n−i−1n−i−1)(n - i + 1) \times \binom{n}{i} \times \binom{i - 2 + n - i - 1}{n - i - 1}。其中 n−i+1n - i + 1 為直徑,(ni)\binom{n}{i} 為所有的 11 位置的方案數, (i−2+n−i−1n−i−1)\binom{i - 2 + n - i - 1}{n - i - 1} 為把多餘的 ii 分配到其他 n−in - i 個位置的方案數(插板法)。

所以總答案為:

∑i=2n−1(n−i+1)(ni)(i−2+n−i−1n−i−1)=∑i=2n−1(n−i+1)(ni)(n−3n−i−1)=(n+1)∑i=2n−1(ni)(n−3n−i−1)−∑i=2n−1i(ni)(n−3n−i−1)=(n+1)∑i=2n−1(ni)(n−3n−i−1)−∑i=2n−1n(n−1i−1)(n−3n−i−1)\begin{aligned} & \sum_{i = 2}^{n - 1} (n - i + 1) \binom{n}{i} \binom{i - 2 + n - i - 1}{n - i - 1} \\ = & \sum_{i = 2}^{n - 1} (n - i + 1) \binom{n}{i} \binom{n - 3}{n - i - 1} \\ = & (n + 1) \sum_{i = 2}^{n - 1} \binom{n}{i} \binom{n - 3}{n - i - 1} - \sum_{i = 2}^{n - 1} i \binom{n}{i} \binom{n - 3}{n - i - 1} \\ = & (n + 1) \sum_{i = 2}^{n - 1} \binom{n}{i} \binom{n - 3}{n - i - 1} - \sum_{i = 2}^{n - 1} n\binom{n - 1}{i - 1} \binom{n - 3}{n - i - 1} \\ \end{aligned}

然而這樣仍然是 O(n)O(n) 的。問題在於如何快速計算那兩個 sigma。以 ∑i=2n−1(ni)(n−3n−i−1)\sum_{i = 2}^{n - 1} \binom{n}{i} \binom{n - 3}{n - i - 1} 為例,它的相當於有 nn 個藍色球和 n−3n - 3 個紅色球,選 ii 個藍色球和 n−i−1n - i - 1 個紅色球的方案數,即是 2n−32n - 3 個球中選擇 n−1n - 1 個球的方案數,也就是 (2n−3n−1)\binom{2n - 3}{n - 1}。

故答案為 (n+1)(2n−3n−1)−n(2n−4n−2)(n + 1)\binom{2n - 3}{n - 1} - n\binom{2n - 4}{n - 2}。

void solve()
{
    int n;
    cin >> n;
    if (n == 2) {
        cout << 1 << endl;
        return ;
    }
    mint ans = (n + 1) * binom(2 * n - 3, n - 1);
    ans -= n * binom(n * 2 - 4, n - 2);
    cout << ans.val() << endl;
}