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

题面

有一棵有根树 \(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. Linux三剑客日志处理系列

    三剑客日志处理系列 一.特殊符号 1.引号系列 必会 引号 含义 单引号 所见即所得,单引号里的内容会原封不动输出 双引号 和单引号类似,对双引号里面的特殊符号进行解析,对于{}花括号(通配符)没有解 ...

  2. bind使用场景之一

  3. .net core 上传文件到本地服务器

    1.本文是上传文件到本地服务器,主要以作者做的业务上传apk为例子,下面直接上代码 [HttpGet, HttpPost, HttpOptions] [Consumes("applicati ...

  4. Mybatis的常用配置-多表关联查询

    Mapper.xml常用配置 全局配置文件(数据库,事物管理,Mapper的注册.打印文件SQL.慢性加载.二级缓存) Mapper配置文件 (定义自定义接口的具体方案;SQL.数据库.数据库与POJ ...

  5. TCP/IP协议(5): IP(Internet Protocol) 协议 —— 连接各个网络的协议

    TCP/IP协议(5): IP(Internet Protocol) 协议 -- 连接各个网络的协议 关于 IP(Internet Protocol) 协议 IP(Internet Protocol) ...

  6. Gold Transportation

    题目 百度 分析 很容易想到二分答案 然后考虑判定 条件很多,奇奇怪怪 那就上网络流吧 边权 \(\leq mid\) 两个城市连边 \(inf\) 源点与所有城市连边,边权为本城市有金矿量 城市与自 ...

  7. JZOJ 5346. 【NOIP2017提高A组模拟9.5】NYG的背包

    题目 分析 很神奇的贪心 \(Code\) #include<cstdio> #include<algorithm> using namespace std; typedef ...

  8. 跳板攻击之:reGeorg 代理转发

    跳板攻击之:reGeorg 代理转发 郑重声明: 本笔记编写目的只用于安全知识提升,并与更多人共享安全知识,切勿使用笔记中的技术进行违法活动,利用笔记中的技术造成的后果与作者本人无关.倡导维护网络安全 ...

  9. 初学 Socket.io

    概念 Socket.io 是一个支持客户端和服务器之间的低延迟.双向和基于事件的通信的库,除了支持 JavaScript 以外,还支持 Java.Python.Golang. Socket.io 构建 ...

  10. 跟女朋友介绍十个常用的 Python 内置函数,她夸了我一整天

    内置函数是什么 了解内置函数之前,先来了解一下什么是函数 将使用频繁的代码段进行封装,并给它起一个名字,当我们使用的时候只需要知道名字就行 函数就是一段封装好的.可以重复使用的代码,函数使得我们的程序 ...