zoukankan      html  css  js  c++  java
  • [HAOI2018]苹果树

    首先发现一次生长相当于去掉一个分支并增加两个分支, 那么所有树出现的概率都是相同的, 一共有 N! 种树。

    所以要求输出的那个东西就是不便度的平均数 * 树的总数, 即所有树的不便度之和。

    对于某棵树的不便度, 把它拆到边上, 具体地, 这棵树的不便度等于 (sum_u siz(u) * (n - siz(u)))

    设 cntu,s 表示点 u 的 siz 为 s 的方案数。(1≤s≤n-u+1)

    首先, 生成 1~u, (color{red}{u!})

    其次, 决定 u 子树中的点的标号,(color{red}{dbinom {n-u}{s-1}}), 然后生成以 u 为根的子树, (color{red}{s!})

    然后生成整棵树的其余部分,(color{red}{(u-1)(u-1+1)cdots(u-1+(n-u-s+1)-1)} = dfrac{(n-s-1)!}{(u-2)!})

    所以答案就是:

    [sum_{u=1}^nsum_{s=1}^{n-u+1} s(n-s)u!inom{n-u}{s-1}s!frac{(n-s-1)!}{(u-2)!} ]

    这道题的模数不保证是质数, 组合数可以预处理,只需要化掉除法:

    [egin{align} &s(n-s)u!inom{n-u}{s-1}s!frac{(n-s-1)!}{(u-2)!}\ &= sinom{n-u}{s-1}s!(n-s)!(u-1)u end{align} ]

    #include<bits/stdc++.h>
    typedef long long LL;
    using namespace std;
    
    const int N = 2e3 + 3;
    
    int n, mo;
    LL C[N][N], fac[N];
    
    int main() {
    	scanf("%d%d", &n, &mo);
    	fac[0] = 1ll, C[0][0] = 1ll;
    	for(int i = 1; i <= n; ++i) fac[i] = fac[i-1] * (LL)i % mo;
    	for(int i = 1; i <= n; ++i) {
    		C[i][0] = 1ll;
    		for(int j = 1; j <= n; ++j) C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mo;
    	}
    	LL ans = 0ll;
    	for(int u = 1; u <= n; ++u) {
    		for(int s = 1; s <= n-u+1; ++s) {
    			ans += (LL)s * C[n-u][s-1] % mo * fac[s] % mo * fac[n-s] % mo * (LL)u % mo * (LL)(u-1) % mo;
    			ans %= mo;
    		}
    	}
    	cout << (ans%mo + mo) % mo;
    	return 0;
    }
    
  • 相关阅读:
    1.1【基本路由原理】(二层转发原理)1
    NP课前资料2-IOU的传统安装方式
    NP课前资料1-安装GNS3桥接ASA
    1.2 数据仓库的特性
    1-1 事务型处理与分析型处理
    易用性测试关注点(转)
    Jenkins+svn+ant+tomcat持续集成
    并发数计算
    性能测试需求采集
    性能测试指标分析与监控
  • 原文地址:https://www.cnblogs.com/tztqwq/p/14351884.html
Copyright © 2011-2022 走看看