「Luogu 4841」城市规划

题目链接:Luogu 4841

阿狸的国家有 $n$ 个城市,现在国家需要在某些城市对之间建立一些贸易路线,使得整个国家的任意两个城市都直接或间接的连通。

为了省钱,每两个城市之间最多只能有一条直接的贸易路径。对于两个建立路线的方案,如果存在一个城市对,在两个方案中是否建立路线不一样,那么这两个方案就是不同的,否则就是相同的。现在你需要求出一共有多少不同的方案。

换句话说,你需要求出 $n$ 个点的简单(无重边无自环)无向连通图数目。由于这个数字可能非常大,你只需要输出方案数对 $1004535809 = 479 \times 2 ^ {21} + 1$ 取模的值即可。

数据范围:$1 \le n \le 1.3 \times 10 ^ 5$。


Solution

有标号无向连通图计数。

设 $f_i$ 表示 $i$ 个点的无向连通图数量,$g_i$ 表示 $i$ 个点的无向图数量。那么我们考虑 $f_i, g_i$ 的指数型生成函数:

$$ F(x) = \sum_{i = 0} ^ {\infty} \frac{f_i x^i}{i!} $$

我们枚举连通块数量 $k$ 得到:

$$ G(x) = \sum_{k = 0} ^ {\infty} \frac{F ^ k (x)}{k!} $$

即:

$$ G = e ^ F \\ F = \ln G $$

显然有:

$$ g_i = \frac{2 ^ {\binom{i}{2}}}{i!} $$

直接上多项式板子!

时间复杂度:$\mathcal O(n \log n)$。


Code

/* 此处省略多项式模板 */

int main() {
    int n;
    scanf("%d", &n);
    Vec A(n + 1);
    A[0] = 1;
    int fac = 1, c = 0;
    for (int i = 1; i <= n; i++) {
        fac = 1LL * fac * i % MOD;
        A[i] = 1LL * pow(2, c) * inv(fac) % MOD;
        c = (c + i) % (MOD - 1);
    }
    printf("%d\n", 1LL * ln(A)[n] * fac % MOD);
    return 0;
}

发表评论