[CodeForces 156D] Clues(Prufer 序列 + 多項式定理) | 錯題本

題目

[CodeForces 156D] Clues

分析

記聯通塊個數爲 kk,枚舉每個聯通塊的度數 did_ii=1kdi=2(k1)\sum_{i = 1}^{k} d_i = 2(k - 1),每條邊的貢獻爲 22,因此度數和爲 2(k1)2(k - 1)),用重排列計算方案數,並且對於一個聯通塊,取裏面一個點的方案數爲聯通塊的大小 sis_i,可得答案爲 i=1kdi=2(k1), di1((i=1k(di1))!i=1k((di1)!)i=1ksidi)=i=1kdi=2(k1), di1((k2)!i=1k((di1)!)i=1ksidi)\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}pi=di1p_i = d_i - 1,則原式變爲 i=1kpi=k2, pi0((k2)!i=1k(pi!)i=1ksipi+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=1ksi)k2=i=1kpi=k2,pi0((k2)!i=1k(pi!)i=1ksipi)\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=1ksi)k2i=1ksi=nk2i=1ksi\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=1k = 1 的情況,並且要輸出 1 % MOD

錯因

  • 並查集都能寫錯;
  • 沒有特判 k=1k = 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章