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

题面

有一棵有根树 \(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风格规范(转载) https://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/python ...

  2. Seata分布式事务

    使用Seata版本:1.6.1(2023/2/6最新版)该版本存在很多坑,相较于1.0版本,配置上存在很多差别,如果你的版本不同,请不要参考本文. 1.6.1配置存在许多问题,比较难找,如果你使用1. ...

  3. 视觉SLAM:滑动窗口

    1.SLAM问题 1.1建模 考虑某个状态 \(\xi\),以及一次与该变量相关的观测 \(r_{i}\).由于噪声存在,观测服从概率分布 \(p(r_{i}|\xi)\).多个观测时,各个测量值相互 ...

  4. debug补充、员工管理系统、字符编码、文件操作

    一.debug补充 在当前行的代码左侧点击一下,会出现一个红点(打断点) 在代码编辑区域右键选择debug,不要在选择run 二.员工管理系统 # 创建大列表 staff_info_list = [] ...

  5. python破解zip或者rar压缩文件

    转载博客园python大师:https://www.cnblogs.com/daniumiqi/p/12167764.html

  6. 个人博客系统Typecho情侣主题模板Cupid

    个人博客系统Typecho情侣主题模板Cupid 转载:https://zcjun.com/3175.html

  7. PHP的25种框架

    本篇文章给大家分享的内容是25种PHP框架 -有着一定的参考价值,有需要的朋友可以参考一下. 世界流行框架汇总 在项目开发中,一些架构和代码都是重复的,为了避免重复劳动,于是各种各样的框架诞生了. 在 ...

  8. nvm作用、下载、使用、常见问题

    一.nvm是什么及作用 nvm全名node.js version management,同等于nodejs的版本管理工具.当不同项目使用不同版本nodejs且不统一时,这时就用到nvm进行不同项目不同 ...

  9. CSS3--点击弹出菜单动画

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...

  10. Qt实现简单的TCP协议(客户端的实现)

    1.QT提供了QTcpSocket类,可以直接实例化一个客户端.需要在pro文件中添加   QT += network 2.连接服务端 connect(connectbutton,SIGNAL(cli ...