JSOI 2019 简要题解
JSOI 都是好题, 还不毒瘤.
「JSOI2019」精准预测
题目链接
解题思路
这是一道 2-SAT 题.
首先有一个朴素的想法, 对于每个时刻 $t$ 每个火星人 (?) $x$, 拆为两个点 $(x, t, 0)$, $(x, t, 1)$, 分别代表生存和死亡. 那么由题意有连边
论据: “火星人是不能够复活的”.
对于预测 $0$, 有连边
后者来源为 2-SAT 的性质, 下文同理.
对于预测 $1$, 有连边
对于计算答案, 可看作统计点 $(x, T + 1, 0)$ 到达其余形同 $(y, T + 1, 1)$ 点的个数, 即有向图传递闭包, 可利用 bitset
优化复杂度. 同时, 建出的图一定是一个 DAG, 直接 DFS 一遍即可. 当然跑强连通分量也是可以的.
同时要注意 $(x, T + 1, 0)$ 可达 $(x, T + 1, 1)$ 的情况, 打标记特判即可.
此时得到了时间复杂度为 $O(\frac{Tnm}{w})$, 空间复杂度为 $O(Tnm)$ 的优秀做法, 令人感到快乐.
注意实际有用处的点只有 $2 (n + 2m)$ 个, 即每次预测涉及的点, 以及 $T + 1$ 时刻计算答案的部分. 同时, 可以利用分块求解的技巧. 设块大小为 $B$, 每次只统计块大小 $B$ 规模的答案, 将每次计算后得出的结果合并即可.
综上, 时间复杂度 $O(\frac{n}{B} \cdot \frac{m(n + m)}{w})$, 空间复杂度 $O\big(B(n + m)\big)$, 此处的 $B$ 可取 $10 ^ 4$.
代码实现
1 | // LOJ #3101 |
「JSOI2019」神经网络
题目链接
解题思路
这是一道不知道为什么就是写了很久调了很久的题 (
首先有一个重要的性质, 哈密顿回路经过的树边, 一定不是同一棵树上相邻的链组成的. 换言之, 树上相邻两条链在哈密顿回路上并不相邻. 根据这个性质, 可对于每棵树求出分出 $k$ 条链的方案数, 再利用容斥原理计算答案.
接下来的问题分作两部分
计算每个树中, 分出 $k$ 条链的方案数.
(其实是一个很经典的树形 DP, 譬如「九省联考 2018」林克卡特树 的某档部分分.)
设 $g(u, k, s)$ 表示 $u$ 的子树内, 总共组成 $k$ 条完整的链, 且包含节点 $u$ 的链状态为 $s$ 的方案数. 其中 $s \in \{ 0, 1, 2 \}$, 分别形同
.
,/
,/\
, 也就是节点 $u$ 在子树一侧的链中保留的度数.同时, 认为只有形成 $s = 2$ 的局面才认为是一条完整的链, 也就是说, $s = 0, 1$ 的情况并未计入总链数. 那么有初值
转移则枚举形成链条数即可, 具体式子可参考代码. 大体上讲, 转移分作两类
- 儿子 $v$ 已形成一条完整的链, 此时直接合并到 $u$.
- 儿子 $v$ 未形成完整的链, 此时需找到 $u$ 中对应状态合并.
注意在合适的时机更新
size
以保证时间复杂度, 以及在合并两条 $1$ 类链时, 要考虑到哈密顿回路上两条链顺序不同的影响, 乘 $2$ 作为系数.容斥计算答案.
先忽略回路的影响, 计算哈密顿通路的个数. 记当前树中分出链个数为 $i$ 的方案数为 $f_i$, 那么根据容斥原理, 可得出当前树组成哈密顿通路个数的 EGF 为
稍微解释一下. 考虑用补集交计算集合交. 枚举 $j$ 表示当前的 $i$ 条链, 包含 $j$ 部分在哈密顿通路上不相邻, 剩余 $i - j$ 部分相邻. 此时不相邻的 $j$ 部分在合并 EGF 时需去除标号影响, 因此乘系数 $\frac{1}{j!}$.
交换枚举顺序, 得到
在得出 $f_i$ 之后容易在 $O(n ^ 2)$ 的时间复杂度内计算. 对于 $m$ 棵树的情况, 直接将每棵树的 EGF 相乘就好了.
记上述结果为 $H(x) = \sum\limits_{k = 0} ^ \infty \dfrac{h_k}{k!} x ^ k$, 考虑圆排列公式, 得到满足哈密顿回路限制时的 EGF 为
对 $F(x)$ 对应数列的每一项求和即可.
时间复杂度为 $O\Big(\left(\sum k_i\right) ^ 2\Big)$, 瓶颈在于树形 DP.
代码实现
1 | // LOJ #3102 |
「JSOI2019」节日庆典
题目链接
解题思路
这是一道串串题, 但是同市面上套数据结构的串串题不大相同.
题目所求即对一个串 $S$ 的每个前缀, 求最小循环表示的开始位置. 如果有多个, 输出最小的.
首先不加证明地给出两个性质
对于前缀 $S_{1 \ldots k}$, 我们称能够成为该前缀最小循环表示开始位置的位置为候选点.
对于两个位置 $i < j$. 如果 $\mathrm{LCP}(S_{i\ldots n}, S_{j\ldots n}) \le k - j$, 那么 $i$, $j$ 之间肯定有一个不是候选点.
对于两个位置 $i < j$, 假设 $\mathrm{LCP}(S_{i\ldots n}, S_{j\ldots n}) > k - j$, 如果有 $k - j \le j - i$, 那么 $j$ 不是候选点.
摘抄自官方题解, 同时官方题解有具体证明. UOJ 用户群有售 (雾. 也可以参考 yhx-12243 的证明.
利用性质 1 时, 假定已经维护出前缀 $S_{1 \ldots k-1}$ 的候选点集合, 那么该集合内元素一定满足 $\mathrm{LCP}(S_{i \ldots n}, S_{j \ldots n}) > (k - 1) - j$. 现在新加入位置 $S_k$, 只需比较 $S_{i + (k - j)}$, $S_{k}$ 的字典序大小即可.
借助于性质 2, 可以得到候选点个数不会超过 $O(\log n)$, 那么大力维护候选点集合就好了.
而对于候选点, 可通过 Z-Algorithm 比较循环同构串字典序. 因为其本质是在比较整个串和该串的某个后缀的 LCP. 同时要注意超过长度 $n$, 又从 $1$ 开始的部分.
时间复杂度 $O(n \log n)$.
代码实现
1 | // LOJ #3103 |