[HAOI2018]苹果树
嘟嘟嘟
这种计数大题就留给南方的计数神仙们做吧……
刚开始我一直想枚举点,考虑新加一个点在根节点的左右子树,以及左右子树大小怎么分配,但是这样太难计算新的点带来的贡献了。
后来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)!\)。
那么答案就出来啦:
\]
#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]苹果树的更多相关文章
- 【BZOJ5305】[HAOI2018]苹果树(组合计数)
[BZOJ5305][HAOI2018]苹果树(组合计数) 题面 BZOJ 洛谷 题解 考虑对于每条边计算贡献.每条边的贡献是\(size*(n-size)\). 对于某个点\(u\),如果它有一棵大 ...
- [洛谷P4492] [HAOI2018]苹果树
洛谷题目链接:[HAOI2018]苹果树 题目背景 HAOI2018 Round2 第一题 题目描述 小 C 在自己家的花园里种了一棵苹果树, 树上每个结点都有恰好两个分支. 经过细心的观察, 小 C ...
- [HAOI2018]苹果树(组合数学,计数)
[HAOI2018]苹果树 cx巨巨给我的大火题. 感觉这题和上次考试gcz讲的那道有标号树的形态(不记顺序)计数问题很类似. 考虑如果对每个点对它算有贡献的其他点很麻烦,不知怎么下手.这个时候就想到 ...
- [BZOJ5305][Haoi2018]苹果树 组合数
题目描述 小 C 在自己家的花园里种了一棵苹果树, 树上每个结点都有恰好两个分支. 经过细心的观察, 小 C 发现每一天这棵树都会生长出一个新的结点. 第一天的时候, 果树会长出一个根结点, 以后每一 ...
- [BZOJ5305][HAOI2018]苹果树 组合数学
链接 小 C 在自己家的花园里种了一棵苹果树, 树上每个结点都有恰好两个分支. 经过细心的观察, 小 C 发现每一天这棵树都会生长出一个新的结点. 第一天的时候, 果树会长出一个根结点, 以后每一天, ...
- [BZOJ5305] [HAOI2018] 苹果树 数学 组合计数
Summary 题意很清楚: 小 \(C\) 在自己家的花园里种了一棵苹果树, 树上每个结点都有恰好两个分支. 经过细心的观察, 小 \(C\) 发现每一天这棵树都会生长出一个新的结点. 第一天的时候 ...
- Luogu4492 [HAOI2018]苹果树 【动态规划】
题目分析: 思路不难想,考虑三个dp状态$f,g,d$. $g[i]$表示有$i$个点的堆的数量 $d[i]$表示有$i$个点的情况下所有的方案数中点到根的距离和 $f[i]$表示要求的答案. 不难发 ...
- HAOI2018苹果树
题解 首先所有生成树的情况树是\(n!\)的,因为第一次有1中方法,第二次有两种放法,以此类推... 然后我们发现距离这种东西可以直接枚举每条边算贡献. 于是我们枚举了一个点\(i\),又枚举了这个点 ...
- BZOJ.5305.[HAOI2018]苹果树(组合 计数)
LOJ BZOJ 洛谷 BZOJ上除了0ms的Rank1啦.明明这题常数很好优化的. 首先,\(n=1\)时有\(2\)个位置放叶子,\(n=2\)时有\(3\)个... 可知\(n\)个点的有标号二 ...
- 洛谷P4492 [HAOI2018]苹果树(组合数)
题意 题目链接 Sol 有点自闭,.我好像对组合数一窍不通(~~~~) Orz shadowice // luogu-judger-enable-o2 #include<bits/stdc++. ...
随机推荐
- JavaSE-基础语法(四)-javaSE进阶
javaSE进阶 三.异常 四.多线程 五.Lambda表达式 六.IO流 七.网络编程 八.新特性 13.异常体系14.异常分类15.声明抛出捕获异常16.自定义异常17.线程概念18.线程同步19 ...
- WPF实现主题更换的简单DEMO
WPF实现主题更换的简单DEMO 实现主题更换功能主要是三个知识点: 动态资源 ( DynamicResource ) INotifyPropertyChanged 接口 界面元素与数据模型的绑定 ( ...
- 6.方法_EJ
第38条: 检查参数的有效性 对于这一条,最常见的莫过于检查参数是否为null. 有时出现调用方未检查传入的参数是否为空,同时被调用方也没有检查参数是否为空,结果这就导致两边都没检查以至于出现null ...
- javascript算法-插入排序
原理跟java那篇文章一样,只是语言不同而已 var InsertSort = function( _n ){ this.maxSize = _n; this.arr = []; this.init ...
- angular select2 下拉单选和多选的取值赋值
官网:http://select2.github.io/examples.html 兼容性: 引入文件 /select2.min.js /select2.min.css html <select ...
- sass安装和语法
1.简介 sass 它的基本思想是,用一种专门的编程语言,进行网页样式设计,然后再编译成正常的CSS文件.这被叫做“css预处理器”(css preprocessor).它提供了很便利的语法,节省了我 ...
- AI在汽车中的应用:实用深度学习
https://mp.weixin.qq.com/s/NIza8E5clC18eMF_4GMwDw 深度学习的“深度”层面源于输入层和输出层之间实现的隐含层数目,隐含层利用数学方法处理(筛选/卷积)各 ...
- 2 >&1 的准确含义
1. 2代表标准错误,2 > 表示重定向,就是把标准错误重定向到 1中,这个1如果想表示标准输出的话,就必须在前面加 & 2. 正常情况下,下面这个会有很多错误信息,但是加上2>& ...
- 深入理解Java虚拟机04--类结构文件
一.程序存储格式 统一的程序存储格式:不同平台的虚拟机于所有平台都统一使用程序存储格式——字节码(ByteCode); Java 虚拟机不关心 Class 文件的来源,而只和“Class文件" ...
- 架构师成长之路-基于android fragment通信的面向对象的万能接口
前言 开发一个app时,常用Activity和Fragment,由于操作方便Fragment越来越受欢迎,这样就避免不了Activity和Fragment.Fragment和Fragment之间的通信 ...