BZOJ5305: [HAOI2018]蘋果樹

傳送門php

果真只有我這種菜雞纔會用這種菜雞作法QwQ
對於一類要求指望的題目,有一個無腦的作法:
設機率爲 \(f\),指望爲 \(g\)
每次合併兩個二元組 \(<f_1,g_1>,<f_2,g_2>\) 的方法顯然爲 \(<f_1\times f_2,g_1\times f_2+f_1\times g_2>\)c++

對於這一道題,設 \(i\) 個點的樹的方案數 \(f_i\),到根的距離和爲 \(g_i\),距離總合 \(h_i\)
顯然 \(f_i=i!\)
(我TM寫了個這個東西\(f[0]=f[1]=1,f[i]=\sum f[j-1]f[i-j]\binom{i-1}{j-1}\)結果發現我是zz)
\(g_i\) 的合併要將左右的樹的 \(g\) 分別加上 \(1\)
\(h_i\) 的合併要將左右的樹的 \(g\) 分別加上 \(1\) 而後拼起來再加上左右的 \(h\)
最後 \(h_i\) 還要算上 \(g_i\)spa

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn(2005);

int n, mod, c[maxn][maxn], f[maxn], g[maxn], h[maxn];

inline void Inc(int &x, const int y) {
    x = x + y >= mod ? x + y - mod : x + y;
}

inline int Add(const int x, const int y) {
    return x + y >= mod ? x + y - mod : x + y;
}

int main() {
    int i, j, tmp1, tmp2;
    scanf("%d%d", &n, &mod), f[0] = f[1] = c[0][0] = 1;
    for (i = 2; i <= n; ++i) f[i] = (ll)f[i - 1] * i % mod;
    for (i = 1; i <= n; ++i)
        for (c[i][0] = j = 1; j <= i; ++j) c[i][j] = Add(c[i - 1][j - 1], c[i - 1][j]);
    for (i = 2; i <= n; ++i) {
        for (j = 1; j <= i; ++j) {
            Inc(g[i], tmp1 = (ll)Add((ll)f[i - j] * (i - j) % mod, g[i - j]) * c[i - 1][j - 1] % mod * f[j - 1] % mod);
            Inc(g[i], tmp2 = (ll)Add((ll)f[j - 1] * (j - 1) % mod, g[j - 1]) * c[i - 1][j - 1] % mod * f[i - j] % mod);
            Inc(h[i], (ll)Add((ll)h[i - j] * f[j - 1] % mod, (ll)h[j - 1] * f[i - j] % mod) * c[i - 1][j - 1] % mod);
            Inc(h[i], Add((ll)tmp1 * (j - 1) % mod, (ll)tmp2 * (i - j) % mod));
        }
        Inc(h[i], g[i]);
    }
    printf("%d\n", h[n]);
    return 0;
}
相關文章
相關標籤/搜索