The 2020 ICPC Asia Macau Regional Contest B Boring Problem
Posted Dreamunk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了The 2020 ICPC Asia Macau Regional Contest B Boring Problem相关的知识,希望对你有一定的参考价值。
比较模板的题。
题目
给定一个字符串 \\(S\\),\\(n\\) 个字符串 \\(T_1,T_2,\\dots,T_n\\),每个串长度都是 \\(m\\),一个长度为 \\(k\\) 的有理数序列 \\(p_1,p_2,\\dots,p_k\\) 保证 \\(\\sum p_i=1\\)。每个字符串由前 \\(k\\) 个小写字母构成。
我们进行下面的过程:
- 如果存在 \\(j(1\\le j\\le n)\\) 满足 \\(T_j\\) 是 \\(S\\) 的子串,那么停止这个过程。
- 否则按 \\(p_i\\) 的概率将第 \\(i\\) 个小写字母加到 \\(S\\) 的末尾,然后继续这个过程。
定义 \\(f(S,T,p)\\) 表示停止的时候 \\(S\\) 的期望长度。
给一个字符串 \\(R\\),对 \\(R\\) 的每个前缀,求出答案。也就是求出 \\(f(R[1\\dots i],T,p)\\) 对 \\(i\\in [1,|R|]\\) 的所有值。
\\(n\\le 100,nm\\le 10000,|R|\\le 10^4\\),答案对 \\(1\\ 000\\ 000\\ 007 取模\\)
题解:
一个显然的做法是建出 \\(T_1,T_2,\\cdots,T_n\\) 的 AC 自动机,则题目相当于在 AC 自动机上随机游走,问走到叶结点之一的期望次数。
设 \\(E(x_i)\\) 表示从 AC 自动机上第 \\(i\\) 个点出发,期望多少次能走到一个叶结点,列方程后高斯消元即得答案。未知数个数达到 \\(O(nm)\\),时间复杂度 \\(O(n^3m^3)\\),过不了。
考虑优化未知数个数。观察方程 \\(E(x_u)=1+\\sum_{c=1}^k p_c E(x_{\\operatorname{next}_{u,c}})\\)。
(\\(\\operatorname{next}_{u,c}\\) 表示从点 \\(u\\) 走 \\(c\\) 的转移边到的结点)中,\\(\\operatorname{next}_{u,c}\\) 要么是 Trie 树上 \\(u\\) 的儿子,要么深度不超过 \\(u\\) 的深度。
考虑树剖:对每个点 \\(u\\) 任选一个儿子 \\(v\\) 作为偏爱儿子进行树链剖分。那这个方程就可以看作把 \\(v\\) 用 \\(u\\) 的其他儿子和深度不超过 \\(u\\) 的深度的结点表示出来。
那么我们发现经过代入,每个结点的答案都可以通过一些链顶结点的答案来表示。怎么做呢?我们按从浅到深的顺序来做。注意到对一个方程 \\(E(x_u)=1+\\sum_{c=1}^k p_c E(x_{\\operatorname{next}_{u,c}})\\),它所涉及到的最深层的结点是 \\(u\\) 的全部儿子,而它们除了偏爱儿子 \\(v\\) 以外全是链顶结点。而对于所涉及到的深度不超过 \\(u\\) 的深度的结点,由于我们是按从浅到深的顺序,所以一定已经被表出,代入即可。
由于叶子结点不超过 \\(n\\) 个,所以剖出链的个数 \\(O(n)\\),未知数个数 \\(O(n)\\),总时间复杂度 \\(O(n^3+n^2mk+|R|)\\),可以通过。
此外这题还可以使用概率生成函数。
不熟悉概率生成函数的同学可以先做做 歌唱王国 和 硬币游戏。
首先把输入的 \\(T_1,T_2,\\cdots,T_n\\) 拿去去重。
先考虑 \\(S\\) 初始为空的情况怎么做。
记 \\(F_i(x)=\\sum_{j\\ge 0} f_{i,j}x^j,G(x)=\\sum_{j\\ge 0} g_jx^j\\),其中 \\(f_{i,j}\\) 表示随机第 \\(j\\) 次时恰好跟 \\(T_i\\) 匹配上的概率,\\(g_j\\) 表示随机第 \\(j\\) 次时还没有结束的概率。
根据概率生成函数的基础知识,我们要求的是 \\((\\sum F_i)\'(1)\\)。
由于 \\(g_{j-1}-g_{j}=\\sum_i f_{i,j}\\),于是有 \\(1+xG(x)=G(x)+\\sum_i F_i(x)\\)。
此外我们根据 \\(n\\) 个串的信息还能列出 \\(n\\) 个方程。具体来说,若当前还没有结束随机过程,这时我们在串尾接上 \\(T_i=T_{i,1}T_{i,2}\\cdots T_{i,m}\\) 后,随机过程必然是已经结束了。然而也可能还没有接完 \\(T_i\\) 就已经匹配完了。总之:\\(G(x)\\prod_{k=1}^m(p_{T_{i,k}}x)=\\sum_{j=1}^n F_j(x)\\sum_{l|T_i[1:l]=T_j[m-l+1:m]}\\prod_{k=l+1}^m(p_{T_{i,k}}x)\\)。
我们最终要求 \\((\\sum F_i)\'(1)\\)。由第一个式子:
\\((\\sum F_i)(x)=1+(x-1)G(x)\\)
\\((\\sum F_i)\'(x)=G(x)+(x-1)G\'(x)\\)
\\((\\sum F_i)\'(1)=G(1)\\)
所以我们求的其实就是 \\(G(1)\\)。
由后面的式子,\\(G(1)\\prod_{k=1}^mp_{T_{i,k}}=\\sum_{j=1}^n F_j(1)\\sum_{l|T_i[1:l]=T_j[m-l+1:m]}\\prod_{k=m-l+1}^mp_{T_{j,k}}\\)。
此外还有 \\(\\sum_{j=1}^n F_j(1)=1\\)。
\\(n+1\\) 个方程 \\(n+1\\) 个未知数,可以解了。最后代入即得 \\(G(1)\\)。
接下来是 \\(S\\) 初始不为空的情况,也就是我们给它钦定了一些前缀。
首先如果钦定的前缀里就包含了某个 \\(T_i\\),那就不用做了。
否则考虑照样列方程。第一个方程是不变的。
第二个方程如何改变呢?关键在于,刚刚列方程时在串尾接上 \\(T_i\\) 的操作是在哪里都可以做的,如果使用原来的方程就变成了只有开始随机之后才能接上。实际上还没开始随机的时候也可以往后面加 \\(T_i\\),而这样对原函数方程的贡献形如 \\(\\sum_{k}q_kx^k\\)(除 \\(x\\) 以外都是常数),而代入 \\(1\\) 以后就彻彻底底变成常数了。
因此每次只有常数项有改变,不用每次都高斯消元,只要矩阵求逆后乘向量即可。
时间复杂度 \\(O(n^3+n^2m+nmk+|R|)\\)。
以上是关于The 2020 ICPC Asia Macau Regional Contest B Boring Problem的主要内容,如果未能解决你的问题,请参考以下文章
2020 ICPC Macau A. Accelerator(期望,计数,分治FFT)(每日一题 21.7.6)
The 2019 ICPC Asia Shanghai Regional Contest
The 2019 ICPC Asia Shanghai Regional Contest
The Preliminary Contest for ICPC Asia Yinchuan 2019