为什么会有人推得出来第三题想不出来签到题啊 (⊙_⊙)?

题面

有一棵有根树 \(T\)。从根节点出发,在点 \(u\) 时,设点 \(u\) 还有 \(d\) 个未访问过的儿子,则有 \(\frac1{d+1}\) 的概率向上(深度较小的方向)走一步,有 \(\frac1{d+1}\) 的概率走向一个未访问过的儿子。从根节点往上走则结束游走。

记 \(f(T)\) 为这样游走到达的点的深度之和的期望。

给定 \(N\)(\(N\le10^7\)),对 \((1,2,\dots,N)\) 的所有排列 \(P\),建立小根的笛卡尔树 \(T_P\),求

\[\sum_{P}f(T_p)
\]

答案对给定的正整数 \(mod\) (\(n\lt mod\le2\times10^9\))取模,\(mod\) 不一定是质数。


解析

先分析在 \(T\) 上的游走方法。笛卡尔树是二叉树,若当前点有未访问的儿子,则:

  • 只有一个儿子时,有 \(\frac 12\) 的概率会走向该儿子;
  • 有两个儿子时,有 \(\frac 13\) 的概率第一次就走向该儿子,有 \(\frac 13\times\frac 12\) 的概率第二次走向该儿子,即总共有 \(\frac 12\) 的概率会走向该儿子。

于是我们发现是否会到达一个儿子的概率恒为 \(\frac12\),与儿子个数无关,这会使我们之后的推导方便很多。

考虑到笛卡尔树本身是一个分治结构——从最小值处划分为两个区间分别建笛卡尔树,而一个排列建立笛卡尔树仅仅与排列的元素个数有关。由此可以设计一个以排列元素大小为状态的 DP。

设 \(g_n\) 表示「对 \(n\) 个元素的所有排列 \(P_n\) 建立笛卡尔树 \(T_{P_n}\),其 \(f(T_{P_n})\) 之和」,\(g_N\) 即我们要求的答案。但是深度之和并不好直接计算(尽管可以用期望的线性性拆成单点的贡献,但是之后的推导会绕一个大圈,不如下面的方法直观)。

有一个非常常用的性质:\(\sum dep=\sum siz\),于是设计辅助 DP \(f_n\) 表示「对 \(n\) 个元素的所有排列 \(P_n\) 建立笛卡尔树 \(T_{P_n}\),从根出发期望能够到达多少个点」。

转移则考虑枚举左子树的大小 \(l\),选出左子树的元素 \(\binom{n-1}{l}\)。利用期望的线性性,左子树的贡献为 \(f_l\) 乘上右子树的方案数,一个排列显然和一棵笛卡尔树一一对应,所以贡献即为 \(f_l\times(n-l-1)\)。右子树同理,最后还要加上根的贡献,对于 \(n!\) 种笛卡尔树根的贡献都是 \(1\)。

\[f_n=n!+\frac 12\sum_{l=0}^{n-1}\binom{n-1}{l}\Big((n-l-1)!f_l+l!f_{n-l-1}\Big)
\]

先不管 \(g_n\),继续推导 \(f_n\) 的式子:

\[\begin{aligned}
f_n&=n!+\sum_{l=0}^{n-1}\binom{n-1}{l}(n-l-1)!f_l\\
&=n!+\sum_{l=0}^{n-1}(n-1)!\frac{f_l}{l!}
\end{aligned}
\]

这么多阶乘容易让人联想到指数生成函数的样子,不妨化一下:

\[\frac{f_n}{n!}=1+\frac 1n\sum_{l=0}^{n-1}\frac{f_l}{l!}
\]

显然可以把 \(\frac{f_n}{n!}\) 看成一个整体,发现转移式的主体是一个前缀和。记 \(F_n\) 为 \(\frac {f_i}{i!}\) (\(i\ge1\))的前缀和,则式子可以简化为:

\[F_n-F_{n-1}=1+\frac 1nF_{n-1}\to F_n=1+\frac{n+1}{n}F_{n-1}
\]

\(F_0=0\),多次迭代过后可以得到 \(F_n\) 的通项。

\[F_n=\sum_{i=2}^{n+1}\frac{n+1}{i}
\]

有一个类似于调和级数前 \((n+1)\) 项的东西,设调和级数前 \(n\) 项为 \(H_n\)。

\[\begin{align}
F_n=(n+1)(H_n-1)&\tag{1}
\end{align}
\]

现在回头看一看 \(g_n\),大致转移与 \(f_n\) 相同,但是根的贡献是 \(f_n\),也即 \(siz_n\) 的期望值(所以先推导 \(f\))。

\[\begin{aligned}
g_n&=f_n+\frac12\sum_{l=0}^{n-1}\binom{n-1}{l}\Big((n-l-1)!g_l+l!g_{n-l-1}\Big)\\
&=f_n+\sum_{l=0}^{n-1}\binom{n-1}{l}(n-l-1)!g_{l}\\
&=f_n+\sum_{l=0}^{n-1}(n-1)!\frac{g_l}{l!}\\
&=n!+\sum_{l=0}^{n-1}(n-1)!\frac{g_l+f_l}{l!}
\end{aligned}
\]

同样的,我们记 \(G_n\) 为 \(\frac{g_i}{i!}\) 的前缀和,把 \((1)\) 代入。

\[\begin{align}
G_n-G_{n-1}&=1+\frac 1n(F_{n-1}+G_{n-1})\notag\\
&=H_n+\frac 1nG_{n-1}&\notag\\
\to G_n&=H_n+\frac{n+1}{n}G_{n-1}&\tag{2}
\end{align}
\]

对 \((2)\) 进行迭代也可以得到 \(G_n\) 的通项公式:

\[G_n=\sum_{i=1}^{n}\frac{n+1}{i+1}H_i
\]

我们要算的答案是 \(g_n=n!(G_n-G_{n-1})\),由于 \(mod\) 不一定是质数,那还得继续推式子。

\[\begin{aligned}
g_n&=n!\Big(H_n+\sum_{i=1}^{n-1}\frac{H_i}{i+1}\Big)\\
&=n!H_n+n!\sum_{i=2}^{n}\frac{1}{i}\sum_{j=1}^{i-1}\frac{1}{j}\\
&=n!H_n+\sum_{1\le i\lt j\le n}\frac{n!}{ij}
\end{aligned}
\]

这样分母就可以全部抵消了,预处理调和级数前 \(n\) 项系数的前缀和与后缀和可以 \(\mathcal O(n)\) 求解。


源代码

/* Lucky_Glass */
#include <cstdio>
#include <cstring>
#include <algorithm> const int N = 1e7 + 10;
typedef long long llong; int mod; inline int reduce(llong key) {
return int((key %= mod) < 0 ? key + mod : key);
} int pre[N], suf[N]; int main() {
freopen("cartesian.in", "r", stdin);
freopen("cartesian.out", "w", stdout); int n; scanf("%d%d", &n, &mod); pre[0] = 1;
for (int i = 1; i <= n; ++i) pre[i] = reduce(1ll * pre[i - 1] * i);
suf[n + 1] = 1;
for (int i = n; i; --i) suf[i] = reduce(1ll * suf[i + 1] * i); int ans = 0;
for (int i = 1; i <= n; ++i)
ans = reduce(ans + 1ll * pre[i - 1] * suf[i + 1]); int ex_ans = 0;
for (int i = 2, tmp = 0; i <= n; ++i) {
tmp = reduce(pre[i - 2] + (i - 1ll) * tmp);
ex_ans = reduce(ex_ans + 1ll * tmp * suf[i + 1]);
} ans = reduce(1ll * ans + ex_ans);
printf("%d\n", ans);
return 0;
}

THE END

Thanks for reading!

霓虹中 错落影像
满城声色褪去喧嚷
废墟上 余碑文几行
未铭记何谈淡忘

——《岁月成碑》By 乐正绫/Days

> Link 岁月成碑 - 网易云

「SOL」打扫笛卡尔cartesian (模拟赛)的更多相关文章

  1. 「HGOI#2019.4.19省选模拟赛」赛后总结

    t1-Painting 这道题目比较简单,但是我比较弱就只是写了一个链表合并和区间DP. 别人的贪心吊打我的DP,嘤嘤嘤. #include <bits/stdc++.h> #define ...

  2. 笛卡尔遗传规划Cartesian Genetic Programming (CGP)简单理解(1)

    初识遗传算法Genetic Algorithm(GA) 遗传算法是计算数学中用于解决最优化的搜索算法,是进化算法的一种.进化算法借鉴了进化生物学中的一些现象而发展起来的,这些现象包括遗传.突变.自然选 ...

  3. 笛卡尔树Cartesian Tree

    前言 最近做题目,已经不止一次用到笛卡尔树了.这种数据结构极为优秀,但是构造的细节很容易出错.因此写一篇文章做一个总结. 笛卡尔树 Cartesian Tree 引入问题 有N条的长条状的矩形,宽度都 ...

  4. 「CSP-S模拟赛」2019第四场

    「CSP-S模拟赛」2019第四场 T1 「JOI 2014 Final」JOI 徽章 题目 考场思考(正解) T2 「JOI 2015 Final」分蛋糕 2 题目 考场思考(正解) T3 「CQO ...

  5. 「NOWCODER」CSP-S模拟赛第3场

    「NOWCODER」CSP模拟赛第3场 T1 货物收集 题目 考场思路即正解 T2 货物分组 题目 考场思路 题解 60pts 算法:一维 DP 100pts 算法:一维 DP ?线段树 + 单调栈 ...

  6. #10471. 「2020-10-02 提高模拟赛」灌溉 (water)

    题面:#10471. 「2020-10-02 提高模拟赛」灌溉 (water) 假设只有一组询问,我们可以用二分求解:二分最大距离是多少,然后找到深度最大的结点,并且把它的\(k\)倍祖先的一整子树删 ...

  7. #10470. 「2020-10-02 提高模拟赛」流水线 (line)

    题面:#10470. 「2020-10-02 提高模拟赛」流水线 (line) 题目中的那么多区间的条件让人感觉极其难以维护,而且贪心的做法感觉大多都能 hack 掉,因此考虑寻找一些性质,然后再设计 ...

  8. POJ 2201 Cartesian Tree ——笛卡尔树

    [题目分析] 构造一颗笛卡尔树,然后输出这棵树即可. 首先进行排序,然后用一个栈维护最右的树的节点信息,插入的时候按照第二关键字去找,找到之后插入,下面的树成为它的左子树即可. 然后插入分三种情况讨论 ...

  9. 「CSP-S模拟赛」2019第三场

    目录 T1 「POI2007」山峰和山谷 Ridges and Valleys 题目 考场思路(几近正解) 正解 T2 「JOI 2013 Final」 现代豪宅 题目 考场思路(正解) T3 「SC ...

  10. 「CSP-S模拟赛」2019第一场

    目录 T1 小奇取石子 题目 考场思路 正解 T2 「CCO 2017」专业网络 题目 考场思路 题解 T3 「ZJOI2017」线段树 题目 考场思路 正解 这场考试感觉很奇怪. \(T1.T2\) ...

随机推荐

  1. Python 装饰器原理

    装饰器是 Python 编程中常用的一个功能,可以将通用的逻辑抽象成装饰器,通过装饰器语法应用到不同的目标上,达到增强或修改目标逻辑的目的. 先来看一个简单的例子 # 打印耗时的装饰器 def log ...

  2. KingbaseES函数三态

    理解函数的三态1 VOLATILE: volatile函数没有限制,可以修改数据(如执行delete,insert,update), 使用同样的参数调用可能返回不同的值. STABLE: 不允许修改数 ...

  3. FAQ docker进程启动失败处理案例分享

    docker进程启动失败处理 背景 有同学反馈在启动docker的时候遇到了如下问题:docker启动报错 [root@wuxianfeng ~]# systemctl start docker Jo ...

  4. Linux文件常用操作命令

    Linux文件常用操作命令 一.Linux文件和目录简单操作 1.1 查看文件 ls 查看当前目录下的文件 如: -a 显示所有文件及目录 (ls内定将文件名或目录名称开头为"." ...

  5. 解决 Vue3 中路由切换到其他页面再切换回来时 Echarts 图表不显示的问题

    问题复现: 正常状态下: 切换到其他页面再切换回来: 问题解决: 其实这个问题的解决方式官网写得清清楚楚,我们看看官网怎么解决的: 接下来我用代码解释下这句话(正确的做法是,在图表容器被销毁之后,调用 ...

  6. P27_wxss - 全局样式和局部样式

    全局样式 定义在 app.wxss 中的样式为全局样式,作用于每一个页面. 局部样式 在页面的 .wxss 文件中定义的样式为局部样式,只作用于当前页面. 注意: 当局部样式和全局样式冲突时,根据就近 ...

  7. Docker挂载

    1.挂载的概念 预备:你需要了解docker的基本知识 docker实现了容器部署,那当我们需要配置或者查看容器生成的日志文件怎么办? docker提供了挂载机制:挂载能够将容器内的目录/文件和外部的 ...

  8. 合肥光源储存环束流三维参数测量系统相关PV

    合肥光源纵向震荡数据源相关PV 合肥光源纵向震荡数据源相关PV的增补 在上两文中公布了一些PV,依然有效. 本来发过了,那篇里的PV有些命名的不太好,比如PositionX.PositionY等,感觉 ...

  9. Android:LitePal 在第一次创建表之后第二次创建新的表不生效

    因为业务需求的增长,后续需要继续创建新的表,有可能代码没有任何报错,同时数据库也没有任何新的表加入进来. 修改 litepal.xml 的 version,如果之前是 1,那么修改为 2,总之比之前 ...

  10. Canvas:绘制多边形

    前言 CanvasRenderingContext2D 没有提供绘制多边形的函数,所以只能由我们自己来实现绘制多边形的函数.以六边形为基础,需要用到三角函数:sin 和 cos. 点 A 坐标 (一) ...