杂题记录及简要题解(三)
以下是大概 5 月初开始做的一些题。以前的简要题解都是骗人的。这次真的是简要题解了(大雾
相对之前改良了一下题目名称的格式。
2017 计蒜之道 初赛 - 腾讯狼人杀
二分答案 \(x\) 后原问题变为检验是否存在选取方案 \((V, E)(|V| = k)\) 使得 \(\sum_\limits{e \in E} w_e - xk \cdot (2n- k)\)。式子可以写成 \(\sum_\limits{e \in E} w_e + \frac{k(k - 1)}{2} \cdot 2x - (2n - 1) \cdot xk\),每个点代价设为 \((2n - 1) \cdot x\),每条边边权加上 \(2x\) 之后直接做最大权闭合子图即可。
THUPC 2018 - Citing
将矩阵转化为线性序列后相当于是要做匹配,可以直接用 FFT。
2018 集训队作业 - 复读机
- \(d = 1\):答案为 \(k^n\)。
- \(d = 2\):使用生成函数来表示,答案为 \(n![x^n]\left(\sum_\limits{i = 0}^n [d | i] \frac{x^i}{i!}\right)^k\),化简后是求 \(\frac{n!}{2^k} [x^n](e^x + e^{-x})^k\),二项式定理展开后直接 \(O(k)\) 算就可以了。
- \(d = 3\):还是套用上面的生成函数的式子。使用单位根反演,二项式定理展开后最终是要求 \(\frac{n!}{3^k} [x^n] \sum_\limits{i = 0}^k\binom{k}{i} \sum_\limits{j = 0}^{k - i} \binom{k - i}{j} e^{(i + \omega_3j +\omega_3^{2}(k - i - j))x}\),直接 \(O(k^2)\) 算即可。
ZJOI 2019 - Minimax 搜索
根节点权值改变必然只会变成 \(W + 1\) 或 \(W - 1\),且若变成 \(W + 1\),则只会修改权值 \(< W\) 的点;若变成 \(W - 1\),则只会修改权值 \(> W\) 的点(修改 \(W\) 本身除外)。
为了方便,我们计算使用能量至多为 \(k\) 时的方案数,这样恰好为 \(k\) 的答案可以通过差分得到。可以对两部分的点的贡献分别做 dp。为了防止出现重复,使用补集转化后改为算两部分点中修改后根节点权值不变的方案数。注意到使用能量上限每增加 \(1\),最多只会有两个叶子结点会新产生贡献,于是做动态 dp 就可以了。需要注意一些细节的讨论。
ZJOI 2019 - 语言
树上差分之后用线段树合并来维护树链的并,就可以算单个点的答案。总答案为所有点的答案和除以 \(2\)。
ZJOI 2019 - 浙江省选
\(m = 1\) 相当于做一次这个题。
\(m > 1\) 就做多次,做第 \(k\) 次就相当于求出所有答案为 \(k\) 的直线。单次具体的做法为求出所有剩下直线构成的凸壳,然后用所有答案为 \(1 \sim k - 1\) 的直线对凸壳做区间覆盖,那么一条凸壳上的直线答案为 \(k\) 当且仅当这条直线上存在一个部分被覆盖的次数为 \(k - 1\)。可以二分找每一条答案为 \(1 \sim k - 1\) 的直线在凸壳上的覆盖区间,然后离线做一次扫描线即可。
HNOI 2019 - 白兔之舞
使用单位根反演。那么对于 \(t\),答案为 \(\frac{1}{k} \sum_\limits{j = 0}^{k - 1} \omega_k^{-jt}\left(\omega_{k}^jA + I\right)^L\)。其中 \(A\) 为给定的 \(n \times n\) 的边数矩阵。
后面的东西可以用矩阵快速幂先求出来。之后把前面的 \(\omega_k^{-jt}\) 化为 \(\omega_k^{\binom{j}{2} + \binom{t}{2} - \binom{j + t}{2}}\) 就可以做卷积了。
JSOI 2019 - 精准预测
2-SAT + bitset。每个点直接存整幅图的 bitset 会导致空间不够,可以分成多次做。
JSOI 2019 - 神经网络
假设 \(m\) 棵树分别被拆成了 \(a_1, a_2, \cdots , a_m\) 条链,那么答案即为每棵树拆分的方案数\(\times\)将这些链排列成环使得没有两条相邻的链来自同一棵树的方案数。
对于单棵 \(k\) 个结点的树,拆成 \(1 \sim k\) 条链的方案数可以在 \(O(k^2)\) 的时间内用 dp 算出。注意算每棵树拆分的方案数时,每有一条长度大于 \(1\) 的链还应乘以系数 \(2\),因为链长度大于 \(1\) 时,可以选择从链的两端中任意一端进入。
剩余的部分用生成函数做。可以用容斥减掉同一棵树上的链相邻的方案数。把同一棵树上相邻的链看做整体后,本质上是对所有链做可重集排列,因此单棵树的生成函数为 \(\sum_\limits{i = 1}^k i! f_i \sum_\limits{j = 0}^{i}(-1)^{j} \binom{i - 1}{j} \frac{x^{i - j}}{(i - j)!}\),其中 \(f_i\) 为该棵树拆成 \(i\) 条链的方案数。先不考虑把所有链排成环,只考虑排成序列。记所有树的生成函数的卷积为 \(G(x)\),那么答案为 \(\sum_\limits{i = 1}^{+\infty} i![x^i]G(x)\)。排成环的话只需要强制使得一棵树包含某个结点的链为序列的第一条链,特殊处理一下这棵树的生成函数即可。
JSOI 2019 - 节日庆典
对于一个前缀,可能作为答案的位置只有 \(O(\log n)\) 个。可以直接维护所有位置的集合,然后暴力枚举最优答案。在做最优答案的比较时,发现形式一定是某个后缀与整个串求 lcp,所以可以用 exkmp。
TJOI 2019 - 唱、跳、rap 和篮球
答案为 \(\sum_\limits{i = 0}^{\left\lfloor\frac{n}{4}\right\rfloor} (-1)^i \binom{n - 3i}{i}(n - 4i)! \times \left(\sum_\limits{j = 0}^{a - i} \frac{x^j}{j!}\right)\left(\sum_\limits{j = 0}^{b - i} \frac{x^j}{j!}\right)\left(\sum_\limits{j = 0}^{c - i} \frac{x^j}{j!}\right)\left(\sum_\limits{j = 0}^{d - i} \frac{x^j}{j!}\right)[x^{n - 4i}]\)。
TJOI 2019 - 甲苯先生和大中锋的字符串
建后缀自动机然后差分。
CTSC 2017 - 密钥
将一个A
的权值设为 \(1\),一个B
的权值设为 \(-1\),那么化环为链后可以求出权值的前缀和(记为 \(s\)),之后再枚举所有可能的X
的位置 \(p\),问题转化为求 \(p\) 之后的 \(2k\) 个位置中有多少个位置 \(i\) 满足权值为 \(1\) 且 \(s_i > s_p\)。注意到 \(p\) 每往后移动 \(1\),\(s_p\) 的变化为 \(+1\) 或 \(-1\),因此直接用数组记录每一种前缀和值的数量,在挪动 \(p\) 时做对应增删即可在线性复杂度内做完此题。
CTSC 2017 - 网络
连接的两个点一定在直径上。对直径上的点重标号,记直径上第 \(i\) 个点到第 \(1\) 个点的距离为 \(s_i\),第 \(i\) 个点到除开直径部分以第 \(i\) 个点为根的子树内的点的最长距离为 \(d_i\),假设连接的直径上的两个点为 \(a, b(a < b)\),那么直径上第 \(i\) 个点与第 \(j\) 个点 \((i < j)\) 产生的最长距离为 \(\min\{d_i + d_j + s_j - s_i, d_i + d_j + |s_i - s_a| +|s_j - s_b| + L\}\)。
二分答案 \(w\),那么需要判断直径上所有点对是否都满足 \(d_i + d_j + s_j - s_i \leq w\) 或 \(d_i + d_j + |s_i - s_a| +|s_j - s_b| + L \leq w\) 两条件之一。对于第一个条件可以直接将所有点按 \(d_i + s_i\) 以及 \(d_i - s_i\) 排序,在按 \(d_i + s_i\) 排序后的点序列中顺次枚举 \(j\),那么合法的 \(i\) 在按 \(d_i - s_i\) 排序后的点序列中一定是一个前缀,剩余的后缀部分则需要判断是否满足第二个条件。注意到对于式子 \(d_i + d_j + |s_i - s_a| +|s_j - s_b| + L \leq w\),我们将绝对值拆开并列出所有四种可能的符号情况后,正确的值必然是四种情况中的最大值,那么条件满足等价于四种符号情况的值同时不超过 \(w\),转化可得:
于是可以分别记录四种情况不等式右边的最大值,然后将所有点按 \(s_i\) 排序后顺次枚举 \(a\),判断四种情况合法的 \(b\) 区间是否有交。这一部分用双指针法可以做到复杂度线性。
CTSC 2017 - 游戏
对于第 \(i\) 次游戏,小 R 获胜的概率只由 \(i\) 两边离 \(i\) 最近的两次结果已确定的游戏决定。由于根据贝叶斯公式,有 \(P(B | A, C) = \frac{P(B|A)P(C|B)}{P(C|A)}\),记 \(i\) 两边离 \(i\) 最近的两次结果已确定的游戏的编号为 \(l, r(l < i < r)\),其结果分别为 \(c_l, c_r\),那么有 \(P(x_i = 1|x_l = c_l, x_r = c_r) = \frac{P(x_i = 1 |x_l = c_l)P(x_r = c_r | x_i = 1)}{P(x_r = c_r | x_l = c_l)}\)。可以用一个 set 来维护全局被结果已知的游戏划分成的所有区间,除开区间两端的贡献,每一个区间 \([l, r]\) 的答案即为 \(\sum_\limits{i = l + 1}^{r - 1} \frac{P(x_i = 1 |x_l = c_l)P(x_r = c_r | x_i = 1)}{P(x_r = c_r | x_l = c_l)}\),可以通过线段树维护 dp 矩阵来实现单次快速查询,每次进行修改操作只需删除并插入对应区间,同时顺便维护答案即可。
luogu 5349 - 幂
\({\rm answer} = \sum_\limits{i = 0}^m a_i \sum_\limits{n = 0}^{+\infty} r^nn^i\)。记 \(f_i = \sum_\limits{n = 0}^{+\infty} r^nn^i\),那么有 \(\frac{f_i}{i!} = \sum_\limits{j = 0}^{i - 1}\frac{f_j}{j!} \frac{r}{(1 - r)(i - j)!}\),设 \(F(x) = \sum_\limits{i = 0}^{+\infty} \frac{f_i}{i!} x^i, G(x) = \sum_\limits{i = 1}^{+\infty} \frac{r}{(1 - r)i!}x^i\),那么有 \(F * G + \frac{1}{1 - r} = F\),即 \(F = \frac{-\frac{1}{1 - r}}{G - 1}\),多项式求逆即可。
CEOI 2017 - One-Way Streets
缩完边双后模拟。
CEOI 2017 - Sure Bet
枚举两边选取的总数,然后三分。
CEOI 2017 - Mousetrap
将 \(t\) 点设为根。显然老鼠最终被卡在了一个点后,将这个点到根的路径上的所有支路都堵住最优。可以做一次 dp 预处理出老鼠从每个点出发,被卡在子树内的某个点,最终到 \(t\) 的最小操作次数。
问题是老鼠在最开始可能会往上走。不好直接做,可以二分答案然后从 \(m\) 点暴力往上跳,把支路中不合法的点堵住,判断总操作次数是否足够即可。
CEOI 2017 - Building Bridges
斜率优化 + 分治。
CEOI 2017 - Palindromic Partitions
根据 border 的性质可以证明贪心是对的。
CEOI 2017 - Chase
记 \(s_i\) 表示所有和 \(i\) 相邻的点的 \(F\) 之和。假设选定的一条链为 \(\{a_1, a_2, \cdots , a_k\}\),那么缩掉点 \(a_1\) 的收益为 \(s_{a_1}\),缩掉任意 \(a_i(i > 1)\) 的收益为 \(s_{a_i} - F_{a_{i - 1}}\)。问题的本质还是求最长链,可以直接做树形 dp。
APIO 2016 - Gap
- \(T = 1\):从两边往中间逼近即可求出整个序列。
- \(T = 2\):将 \([a_1, a_N]\) 分成尽量相等的 \(n - 1\) 部分,那么差分值最大的两个数必然不会位于同一部分,可以顺次扫所有区间并记录答案。
IOI 2016 - molecules
若有解,可以证明一定存在一种解是排序后的一段连续区间。直接双指针扫一下即可,也可以二分。
IOI 2016 - railroad
可以将速度值看做结点来建图,对于每一段路 \((s_i, t_i)\),从 \(s_i\) 向 \(t_i\) 连边,再连接一条从 \(+\infty\) 到 \(1\) 的边。现在可以额外加一些从 \(x\) 到 \(x + 1\) 代价为 \(0\) 的边,或者从 \(x + 1\) 到 \(x\) 的代价为 \(1\) 的边。那么问题即为用最少的代价使整幅图构成欧拉回路。
欧拉回路满足经过每一段 \((x, x + 1)\) 的方向向右的边与方向向左的边数量相同,于是可以差分求最小代价。注意这样可能会使一些差分值为 \(0\) 的部分没有边,导致图不连通,所以最后还要做一次最小生成树。
IOI 2016 - paint
预处理出前后缀信息然后分类讨论。通过这些前后缀信息可以求出给定的每一段X
的所有可能出现的位置,差分后做扫描线即可求出整个序列中所有可能为X
的位置。
IOI 2016 - messy
对于区间 \([l, r]\),考虑 \([l, \frac{l + r}{2}]\) 在排列中由哪些位置对应。把这一部分的每个位置依次设为1
插入到集合中,再依次把 \([l, r]\) 内的每个位置设为1
进行查询即可得到排列中哪些位置对应 \([l, \frac{l + r}{2}]\),同时哪些位置对应 \([\frac{l + r}{2} + 1, r]\) 也就随之确定。在类似线段树遍历那样的递归过程中,我们可以不断缩小对应关系的集合,直到一一对应。具体的例子可以参考官方题解。
IOI 2016 - aliens
只保留必要的点后做斜率优化 + 凸优化 dp。
IOI 2017 - wiring
最优解可以拆成若干个形如 subtask 2 所示情况的段。那么可以按段的划分做 dp,用线段树维护区间 dp 最小值进行转移,当然还需要考虑一些边缘上的特殊情况。
IOI 2017 - train
迭代求解,在每一层迭代中 bfs 求出使 Arezou 必败的点,然后删掉即可。