[CodeForces 1109D] Sasha and Interesting Fact from Graph Theory(廣義 Cayley 定理 + 組合數學) | 錯題本

文章目錄

題目

[CodeForces 1109D] Sasha and Interesting Fact from Graph Theory

分析

a,ba, b 不影響答案,不妨設 a=1,b=2a = 1, b = 2,枚舉 a,ba, b 之間的邊數 i[1,n1]i \in [1, n -1],隔板法可得鏈 aba - b 的方案數爲 An2i1Cm1i1A_{n - 2}^{i - 1} \cdot C_{m - 1}^{i - 1}(中間的點編號可以任意取,所以是 An2i1A_{n - 2}^{i - 1})然後考慮剩下的點和邊,首先邊權隨意:An2i1Cm1i1mn1iA_{n - 2}^{i - 1} \cdot C_{m - 1}^{i - 1} \cdot m^{n - 1 - i} 然後考慮剩下的點,這個樹是這個樣子的:樹的形狀
因此接下來我們只需要求 nn 個點構成一個的含有 i+1i + 1 棵樹的森林的數量。根據廣義 Cayley 定理,nn 個點構成的含有 kk 棵樹的森林數量爲 knnk1k \cdot n^{n - k - 1}。因此 nn 個點構成一個的含有 i+1i + 1 棵樹的森林的數量即爲 (i+1)nni2(i + 1) \cdot n^{n - i - 2}

證明:
將鏈 aba - b 縮爲一個點,那麼這個樹的數量爲 nni2n^{n - i - 2},再考慮把上圖中的三角形輪換一圈(因爲 nni2n^{n - i - 2} 算的是各個三角形的圓排列,現在把它轉換成一般排列),答案即爲 (i+1)nni2(i+1)n^{n - i - 2}

因此答案爲 i=1n1An2i1Cm1i1(i+1)nni2mn1i\sum_{i = 1}^{n - 1} A_{n - 2}^{i - 1} C_{m - 1}^{i - 1}(i + 1)n^{n - i - 2}m^{n - 1 - i}

代碼

#include <bits/stdc++.h>

const int MAXN = 1000000;
const int MOD = 1000000007;

int N, M, A1, B1;
int Fac[MAXN + 5], Inv[MAXN + 5];
int PowN[MAXN + 5], PowM[MAXN + 5];

inline int Add(int x, const int &y) {
    x += y; if (x >= MOD) x -= MOD; return x;
}

inline int Mul(const int &x, const int &y) {
    return (long long)x * y % MOD;
}

int Pow(int x, int y) {
    int ret = 1;
    while (y) {
        if (y & 1)
            ret = Mul(ret, x);
        x = Mul(x, x);
        y >>= 1;
    }
    return ret;
}

int A(int n, int m) {
    return Mul(Fac[n], Inv[n - m]);
}

int C(int n, int m) {
    if (m > n) return 0;
    return Mul(Fac[n], Mul(Inv[m], Inv[n - m]));
}

int main() {
    scanf("%d%d%d%d", &N, &M, &A1, &B1);
    int Max = std::max(N, M);
    Fac[0] = PowN[0] = PowM[0] = 1;
    for (int i = 1; i <= Max; i++) {
        Fac[i] = Mul(Fac[i - 1], i);
        PowN[i] = Mul(PowN[i - 1], N);
        PowM[i] = Mul(PowM[i - 1], M);
    }
    Inv[Max] = Pow(Fac[Max], MOD - 2);
    for (int i = Max - 1; i >= 0; i--)
        Inv[i] = Mul(Inv[i + 1], i + 1);
    int Ans = Mul(C(M - 1, N - 2), A(N - 2, N - 2));
    for (int i = 1; i <= N - 2; i++)
        Ans = Add(Ans, Mul(A(N - 2, i - 1), Mul(C(M - 1, i - 1), Mul(i + 1, Mul(PowN[N - i - 2], PowM[N - 1 - i])))));
    printf("%d", Ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章