模模
A
有时知道太多反而不快乐:当你在场上花了约 1h 优化复杂度然后发现开场写的暴力可过:
后记:数据已加强并重测
后后记:其实提交记录已经找不到了,上面是拿 f12 还原的
先花 eps 秒意识到不同的 01 串生成概率是不同的。
具体的,先放完的字符最后一位放在了 \(i\),生成的概率是 \(\frac{1}{2^i}\)。
我们考虑算合法的 01 串的概率和。
然后由于对称性,我们可以强制要求的位上是 0,最后把答案乘 \(2\)。
分讨先放完的是 0 还是 1:
- 先放完 0:
枚举最后一位 \(i\),显然有 \(i \ge \max(a_k, n)\),然后这个的贡献是
\(\displaystyle\sum_{i = \max(a_k, n)}^{2n - 1}\binom{i - k - [i \neq a_k]}{n - k - [i \neq a_k]}\frac{1}{2^i}\).
我们发现把 \(a_k\) 项(如果能取到)单独算,后面是一个对每个 \(k\) 相同的后缀和形式。
然后显然由于 \(\sum k = n\),不同的 \(k\) 只有 \(O(\sqrt n)\) 种,对每个 \(k\) 预处理就可以 \(O(1)\) 回答这个。 - 先放完 1:
枚举最后一位 \(i\),显然有 \(i \ge n, i \notin \{a\}\),然后这个的贡献是
\(\displaystyle\sum_{i = n}^{2n - 1}[i \notin \{a\}]\binom{i - \sum[a_j \le i] - 1}{n - 1}\frac{1}{2^i}\).
这个形式可能有点抽象不太好化简,我们知道枚举 \(a\) 的复杂度是能接受的,把式子写成那个形式,这里我们认为 \(a_{k + 1} = 2n\)
\(\displaystyle\sum_{i = 1}^{k}\sum_{j = a_i + 1}^{a_{i + 1} - 1}\binom{j - i - 1}{n - 1}\frac{1}{2^j}\).
我们会希望后面的和式可以预处理 / 快速计算,如果里面两个变量关系相同就可以预处理,所以我们提一个 \(\frac{1}{2^i}\) 到前面去:
\(\displaystyle\sum_{i = 1}^{k}\frac{1}{2^i}\sum_{j = a_i + 1}^{a_{i + 1} - 1}\binom{j - i - 1}{n - 1}\frac{1}{2^{j - i}}\).
现在我们只要预处理 \(\displaystyle F(n') = \sum_{i = n}^{n'} \binom{i - 1}{n - 1}\frac{1}{2^i}\) 就可以了。
B
先奇偶分离(偶在前),考虑最后把奇偶合并时要 00001111 -> 0[0]0[0][1]1[1]1 -> 01010101。
那么最后一步之前的序列应该是:0 4 2 6 1 5 3 7。
然后考虑分别对奇偶进行排序排成上面这个序列。
考虑使用基数排序,为上面的序列每个值赋一个位置 \(id\):0 1 2 3 3 2 1 0。
然后基数排序从低到高考虑每一位,每一次我们都要把偶数中当前位是 \(1\) 的放到后面(从小到大排序),奇数中当前位是 \(1\) 的放到前面(从大到小)。
然后每次两侧选的位置 \(id\) 相同,数量也相同,就实现了把选的偶数放到后面,奇数放到前面,并且内部有序,然后再进行一步奇偶分离就完成了一层基数排序。
然后跑 \(\log n\) 次就排好序了。
操作次数 \(2\log n + 2\)。
当 \(2 \mid n\) 时最后一步根据 \(n \bmod 4\) 的值有差异,比如 0000011111 -> 0[0]0[0]01[1]1[1]1 -> 0101010101。
然后 \(2 \nmid n\) 时,奇偶个数不等,注意到排序过程中 \(id = 0\) 始终不被选中,所以按照 \(n + 1\) 的标号方式标 \(id\),然后把 \(n + 1\) 丢掉,排的过程是没有影响的。
C
感谢题解的长剖思路。
在有继承关系时还是比较喜欢固定的下标qwq
使用长剖优化 dp,直接继承重儿子的答案,然后从轻儿子转移时只枚举轻儿子的高度。
相当于在整个过程中每条链被枚举了至多 \(1\) 次,总枚举量是 \(O(n)\)。
差分一下,每次计算直径长度在 \([0, lim]\) 中的连通块数。
然后设 \(f_{x, d}\) 表示以 \(x\) 为根的最深点深度为 \(d\) 的合法连通块方案数。
然后在 \(x\) 处合并时,就是要
\([d_1 + d_2 - 2dep_x \le lim]f_{x, d_1} \times f_{y, d_2} \to f_{x, \max(d_1, d_2)}\)。
然后有个 \(\max\) 很不好,考虑枚举 \(d_2\) 分讨贡献:
- \(d_2 \ge d_1\):\(f'_{x, d_2} \gets f_{y, d_2} \times \sum_{d_1 \le \min(d2, lim + 2dep_x - d2)} f_{x, d_1}\);
- \(d_2 < d_1\):\(f'_{x, d_1} \gets f_{x, d_1} \times f_{y, d_2}\)。
注意这里 \(\gets\) 的含义时将后面的值加到前面,不是赋值。
用数据结构维护 \(f\)。
然后第一部分转移就是区间求和然后单点加嘛。
第二部分转移可以发现相当于一个区间乘法(要满足 \(d_1 + d_2 - 2dep_x \le lim\))。
然后不同 \(d_2\) 的修改区间可能会重合,重合部分的乘法系数应该是加起来(不是乘起来),然后相当于是划了 \(O(d_2)\) 段区间乘,对于这个乘法系数的维护我额外写了一个 BIT。
特别注意一点,当 \(x\) 继承重儿子信息时,记得把 \(d > dep_x + lim\) 的 dp 值清空掉。


浙公网安备 33010602011771号