Loading

【题解】ABC290F Maximum Diameter

大龄选手只杀到 E,鉴定为寄。

思路

正解是高明数数,这里提供一种强行推导的方法。

首先有一个死掉的思路:原问题等价于求所有 \(n\) 个点的有标号无根树的直径之和。

如果有什么高明的数数方法可以做当然是好的,但是我不会。

所以我们考虑一个假定的度数序列所产生的直径。

结论:一个度数序列可以构造出树的充要条件是 \(\sum\limits_{i = 1}^n \operatorname{deg}(i) = 2n - 2\),可以构造出来。

对于一个和为 \(2n - 2\) 的序列,极端情况下肯定想构造出一条链。

但是因为存在度数大于等于 \(2\) 的结点,只能构造出一条以叶结点为端点的极长链,然后把剩下的叶结点挂在上面。

假设有 \(k\) 个叶结点,则极长链中包含所有非叶结点和 \(2\) 个作为端点的叶结点,一共有 \(n - k + 2\) 个结点,于是长度为 \(n - k + 1\).

根据结论,随意划分剩下的度数就行。考虑每种直径的贡献,可以插板法推出答案是:\(\sum\limits_{k = 1}^n {n \choose k} {n - 3 \choose n - k - 1} (n - k + 1)\).

有老哥用 NTT 硬草过掉了,比较震撼。

观察到 \(n - k - 1\)\(n - k + 1\) 类似,考虑配凑一下:\(\sum\limits_{k = 1}^n {n \choose k} {n - 3 \choose n - k - 1} (n - k - 1) + 2 \sum\limits_{k = 1}^n {n \choose k} {n - 3 \choose n - k - 1}\).

前面的 \(n - k - 1\) 可以被组合数吸收:\((n - 3) \sum\limits_{k = 1}^n {n \choose k} {n - 4 \choose n - k - 2} + 2 \sum\limits_{k = 1}^n {n \choose k} {n - 3 \choose n - k - 1}\).

前后两项分别两个范德蒙德卷积,得到答案是 \((n - 3) {2n - 4 \choose n - 2} + 2 {2n - 3 \choose n - 1}\).

预处理一下阶乘逆元就可以 \(O(1)\) 算答案了。

代码

#include <cstdio>
using namespace std;

const int maxn = 2e6 + 5;
const int mod = 998244353;

int t, n;
int fac[maxn], invf[maxn];

void init(int lim)
{
    fac[0] = invf[0] = fac[1] = invf[1] = 1;
    for (int i = 2; i <= lim; i++) fac[i] = 1ll * fac[i - 1] * i % mod, invf[i] = 1ll * (mod - mod / i) * invf[mod % i] % mod;
    for (int i = 2; i <= lim; i++) invf[i] = 1ll * invf[i - 1] * invf[i] % mod;
}

int C(int n, int m) { return (n < m ? 0 : 1ll * fac[n] * invf[m] % mod * invf[n - m] % mod); }

int main()
{
    init(2e6);
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d", &n);
        printf("%d\n", (1ll * (n - 3) * C(2 * n - 4, n - 2) % mod + 2ll * C(2 * n - 3, n - 1) % mod) % mod);
    }
    return 0;
}
posted @ 2023-02-20 09:09  kymru  阅读(81)  评论(0编辑  收藏  举报