• BZOJ5305: [HAOI2018]苹果树


    传送门

    果然只有我这种菜鸡才会用这种菜鸡做法QwQ
    对于一类要求期望的题目,有一个无脑的做法:
    设概率为 (f),期望为 (g)
    每次合并两个二元组 (<f_1,g_1>,<f_2,g_2>) 的方法显然为 (<f_1 imes f_2,g_1 imes f_2+f_1 imes g_2>)

    对于这一道题,设 (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]inom{i-1}{j-1})结果发现我是zz)
    (g_i) 的合并要将左右的树的 (g) 分别加上 (1)
    (h_i) 的合并要将左右的树的 (g) 分别加上 (1) 然后拼起来再加上左右的 (h)
    最后 (h_i) 还要算上 (g_i)

    # 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
    ", h[n]);
    	return 0;
    }
    
  • 相关阅读:
    @SpringBootApplication注解的理解
    git详解
    什么是maven?
    redis发布订阅实战
    报文示例
    Cisco的ACI究竟是什么?它和SDN有关系吗?
    IP数据包分析
    ARP数据包分析
    水冷精密空调工作原理
    风冷精密空调工作原理
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/10421077.html
Copyright © 2020-2023  润新知