嘟嘟嘟




这种计数大题就留给南方的计数神仙们做吧……




刚开始我一直想枚举点,考虑新加一个点在根节点的左右子树,以及左右子树大小怎么分配,但是这样太难计算新的点带来的贡献了。

后来lba又提示我枚举边,考虑每一条边的贡献。

这确实是一个好主意,枚举边的同时考虑边两侧的点数,但可怕的是我一直把他当成无根树来做,也就是忽略了树上打父子关系,导致少算了好多形态。

于是题解吵朝我挥了挥手。




既然是有根树,那么我们枚举每一个点,然后枚举的是这个点和他父亲的连边,这样就能不重不漏并且有顺序的枚举所有边了。




考虑点\(i\)这条边的贡献,就是\(size _ i * (n - size_i)\)。

\(size_i\)不确定,但根据题意是可以\(O(n)\)枚举的。

我们枚举\(size_i\),算出当\(size_i\)一定时,这个子树以及子树外有多少种形态。




先考虑子树内:不算标号有\(size_i !\)种形态,因为第一个点只有一种连接方法,第二个点有两种,第三个点有三种……所以\(size_i\)个点就\(size_i !\)种。当形态固定时,考虑标号:因为在\(i\)子树内只可能是标号比\(i\)大的点,所以有\(C_{n - i} ^ {size_i - 1}\)种。那么子树内的所有形态就是\(size_i ! * C_{n - i} ^ {size_i - 1}\)。




接下来我们考虑子树外:在生成点\(i\)的子树之前有\(i!\)种方式,然后我们考虑剩下的\(n - i - size_i\)个点的生成方式,为:\((i - 1) * i * (i + 1) * \ldots * (n - i - size_i - 1)\)。

所以子树外的点的生成方式就是\(i! *(i - 1) * i * (i + 1) * \ldots * (n - i - size_i - 1) = (i - 1) * i * (n - size_i - 1)!\)。

那么答案就出来啦:

\[ans = \sum _ {i = 1} ^{n} \sum _ {size = 1} ^ {n - i + 1} size _ i * (n - size_i) * size_i ! * C_{n - i} ^ {size_i - 1} * (i - 1) * i * (n - size_i - 1)!
\]

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 2e3 + 5;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
} int n, mod; In ll inc(ll a, ll b) {return a + b >= mod ? a + b - mod : a + b;} ll fac[maxn], C[maxn][maxn];
In void init()
{
fac[0] = 1;
for(int i = 1; i <= n; ++i) fac[i] = fac[i - 1] * i % mod;
for(int i = 0; i <= n; ++i) C[i][0] = 1;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= i; ++j)
C[i][j] = inc(C[i - 1][j - 1], C[i - 1][j]);
} int main()
{
n = read(), mod = read();
init();
ll ans = 0;
for(int i = 2; i <= n; ++i)
for(int j = 1; j <= n - i + 1; ++j)
ans = inc(ans, fac[j] * C[n - i][j - 1] % mod * j % mod * (n - j) % mod * fac[n - j - 1] % mod * i % mod * (i - 1) % mod);
write(ans), enter;
return 0;
}

[HAOI2018]苹果树的更多相关文章

  1. 【BZOJ5305】[HAOI2018]苹果树(组合计数)

    [BZOJ5305][HAOI2018]苹果树(组合计数) 题面 BZOJ 洛谷 题解 考虑对于每条边计算贡献.每条边的贡献是\(size*(n-size)\). 对于某个点\(u\),如果它有一棵大 ...

  2. [洛谷P4492] [HAOI2018]苹果树

    洛谷题目链接:[HAOI2018]苹果树 题目背景 HAOI2018 Round2 第一题 题目描述 小 C 在自己家的花园里种了一棵苹果树, 树上每个结点都有恰好两个分支. 经过细心的观察, 小 C ...

  3. [HAOI2018]苹果树(组合数学,计数)

    [HAOI2018]苹果树 cx巨巨给我的大火题. 感觉这题和上次考试gcz讲的那道有标号树的形态(不记顺序)计数问题很类似. 考虑如果对每个点对它算有贡献的其他点很麻烦,不知怎么下手.这个时候就想到 ...

  4. [BZOJ5305][Haoi2018]苹果树 组合数

    题目描述 小 C 在自己家的花园里种了一棵苹果树, 树上每个结点都有恰好两个分支. 经过细心的观察, 小 C 发现每一天这棵树都会生长出一个新的结点. 第一天的时候, 果树会长出一个根结点, 以后每一 ...

  5. [BZOJ5305][HAOI2018]苹果树 组合数学

    链接 小 C 在自己家的花园里种了一棵苹果树, 树上每个结点都有恰好两个分支. 经过细心的观察, 小 C 发现每一天这棵树都会生长出一个新的结点. 第一天的时候, 果树会长出一个根结点, 以后每一天, ...

  6. [BZOJ5305] [HAOI2018] 苹果树 数学 组合计数

    Summary 题意很清楚: 小 \(C\) 在自己家的花园里种了一棵苹果树, 树上每个结点都有恰好两个分支. 经过细心的观察, 小 \(C\) 发现每一天这棵树都会生长出一个新的结点. 第一天的时候 ...

  7. Luogu4492 [HAOI2018]苹果树 【动态规划】

    题目分析: 思路不难想,考虑三个dp状态$f,g,d$. $g[i]$表示有$i$个点的堆的数量 $d[i]$表示有$i$个点的情况下所有的方案数中点到根的距离和 $f[i]$表示要求的答案. 不难发 ...

  8. HAOI2018苹果树

    题解 首先所有生成树的情况树是\(n!\)的,因为第一次有1中方法,第二次有两种放法,以此类推... 然后我们发现距离这种东西可以直接枚举每条边算贡献. 于是我们枚举了一个点\(i\),又枚举了这个点 ...

  9. BZOJ.5305.[HAOI2018]苹果树(组合 计数)

    LOJ BZOJ 洛谷 BZOJ上除了0ms的Rank1啦.明明这题常数很好优化的. 首先,\(n=1\)时有\(2\)个位置放叶子,\(n=2\)时有\(3\)个... 可知\(n\)个点的有标号二 ...

  10. 洛谷P4492 [HAOI2018]苹果树(组合数)

    题意 题目链接 Sol 有点自闭,.我好像对组合数一窍不通(~~~~) Orz shadowice // luogu-judger-enable-o2 #include<bits/stdc++. ...

随机推荐

  1. junit单元测试注意的问题

    1.有返回值的方法不能直接测试 2.带参数的方法不能直接测试 3.访问权限在public一下的方法不能直接测试 4.static静态方法不能直接测试 5.不能给出现前四个条件中任意一个的方法添加@Te ...

  2. Android Studio 学习(五)网络

    HttpURLConnection OkHttp 添加依赖 编辑 app/build.gradle 在dependencies闭包中添加 implementation 'com.squareup.ok ...

  3. Redis配置解读

  4. intellij error updating changes svn解决办法

    乌龟检出的svn版本为1.8,而1.8在IntelliJ 上跑起来貌似有问题, 经过多次尝试,当Format改为1.7后,问题被解决.

  5. memcache 相关

    1.查看memcache是否启动 ps -ef | grep mem

  6. Spring之AOP在XML中的配置方法

    AOP 即 Aspect Oriental Program 面向切面编程 先来一个栗子: <aop:config> <aop:pointcut id="loggerCutp ...

  7. JavaScript 基础(三) - Date对象,RegExp对象,Math对象,Window 对象,History 对象,Location 对象,DOM 节点

    Date对象 创建Date对象 //方法1:不指定参数 var date_obj = new Date(); alert(date_obj.toLocaleString()) //方法2:参数为日期字 ...

  8. js 小写金额转大写

    function smalltoBIG(n) { var fraction = ['角', '分']; var digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', ...

  9. CSS3布局之多列布局columns详解

    columns语法:columns:[ column-width ] || [ column-count ]设置或检索对象的列数和每列的宽度 其中:[ column-width ]:设置或检索对象每列 ...

  10. python itchat 爬取微信好友信息

    原文链接:https://mp.weixin.qq.com/s/4EXgR4GkriTnAzVxluJxmg 「itchat」一个开源的微信个人接口,今天我们就用itchat爬取微信好友信息,无图言虚 ...