题意

给定一个长度为 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;
}