[CodeForces 156D] Clues(Prufer 序列 + 多项式定理) | 错题本

文章目录

题目

[CodeForces 156D] Clues

分析

记联通块个数为 k k ,枚举每个联通块的度数 d i d_i i = 1 k d i = 2 ( k 1 ) \sum_{i = 1}^{k} d_i = 2(k - 1) ,每条边的贡献为 2 2 ,因此度数和为 2 ( k 1 ) 2(k - 1) ),用重排列计算方案数,并且对于一个联通块,取里面一个点的方案数为联通块的大小 s i s_i ,可得答案为 i = 1 k d i = 2 ( k 1 ) ,   d i 1 ( ( i = 1 k ( d i 1 ) ) ! i = 1 k ( ( d i 1 ) ! ) i = 1 k s i d i ) = i = 1 k d i = 2 ( k 1 ) ,   d i 1 ( ( k 2 ) ! i = 1 k ( ( d i 1 ) ! ) i = 1 k s i d i ) \begin{aligned} & \sum_{\sum_{i = 1}^{k} d_i = 2(k - 1),\ d_i \geq 1} \left( \frac{\left( \sum_{i = 1}^{k}(d_i - 1) \right) !}{\prod_{i = 1}^{k} ((d_i - 1)!)} \prod_{i = 1}^{k} {s_i}^{d_i} \right) \\ =& \sum_{\sum_{i = 1}^{k} d_i = 2(k - 1),\ d_i \geq 1} \left( \frac{(k - 2)!}{\prod_{i = 1}^{k} ((d_i - 1)!)} \prod_{i = 1}^{k} {s_i}^{d_i} \right) \end{aligned} p i = d i 1 p_i = d_i - 1 ,则原式变为 i = 1 k p i = k 2 ,   p i 0 ( ( k 2 ) ! i = 1 k ( p i ! ) i = 1 k s i p i + 1 ) \sum_{\sum_{i = 1}^{k} p_i = k - 2,\ p_i \geq 0} \left( \frac{(k - 2)!}{\prod_{i = 1}^{k} (p_i!)} \prod_{i = 1}^{k} {s_i}^{p_i + 1} \right) 又由多项式定理 ( i = 1 k s i ) k 2 = i = 1 k p i = k 2 , p i 0 ( ( k 2 ) ! i = 1 k ( p i ! ) i = 1 k s i p i ) \left( \sum_{i = 1}^{k} s_i \right)^{k - 2} = \sum_{\sum_{i = 1}^{k} p_i = k - 2, p_i \geq 0} \left( \frac{(k - 2)!}{\prod_{i = 1}^{k} (p_i!)} \prod_{i = 1}^{k} {s_i}^{p_i} \right) 因此,原式即为 ( i = 1 k s i ) k 2 i = 1 k s i = n k 2 i = 1 k s i \left( \sum_{i = 1}^{k} s_i \right)^{k - 2} \prod_{i = 1}^{k} s_i = n^{k - 2} \prod_{i = 1}^{k} s_i 注意特判 k = 1 k = 1 的情况,并且要输出 1 % MOD

错因

  • 并查集都能写错;
  • 没有特判 k = 1 k = 1 的情况;
  • 加上特判的时候只 puts("1"),而不是 printf("%d", 1 % MOD)
  • 并查集的 size 可以直接合并。

代码

#include <bits/stdc++.h>

const int MAXN = 100000;

int N, MOD, M, K;

int Fa[MAXN + 5], Size[MAXN + 5];

int Find(int x) {
    return (Fa[x] == x) ? x : (Fa[x] = Find(Fa[x]));
}

int Pow(int x, int y) {
    int ret = 1;
    while (y) {
        if (y & 1)
            ret = (long long)ret * x % MOD;
        x = (long long)x * x % MOD;
        y >>= 1;
    }
    return ret;
}

int main() {
    scanf("%d%d%d", &N, &M, &MOD);
    for (int i = 1; i <= N; i++)
        Fa[i] = i, Size[i] = 1;
    for (int i = 1; i <= M; i++) {
        int u, v; scanf("%d%d", &u, &v);
        int x = Find(u), y = Find(v);
        if (x != y)
            Fa[x] = y, Size[y] += Size[x];
    }
    int Ans = 1;
    for (int i = 1; i <= N; i++) {
        Find(Fa[i]);
        if (Fa[i] == i)
            K++, Ans = (long long)Ans * Size[i] % MOD;
    }
    if (K == 1)
        return printf("%d", 1 % MOD), 0;
    Ans = (long long)Ans * Pow(N, K - 2) % MOD;
    printf("%d", Ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/C20190102/article/details/107149627