ZJOI2022

\((\texttt{Medium} \ 5 / 0)\)

算法一

可以打表发现一个结论:对于一个集合 \(S\)\(T_1\) 的叶结点为 \(S\) 的方案数和 \(T_2\) 的叶结点为 \(\overline{S}\) 的方案数相等。所以我们可以把问题改为:

有两棵树 \(A\)\(B\),它们的生成方式为「\(i\) 的父亲在 \([1, i)\) 上随机」,求两棵树的叶结点集合相同的方案数。

\(f_{i, j, k}\) 表示考虑前 \(i\) 个结点,两棵树分别还有 \(j, k\) 个儿子需要挂的方案数,我们有转移:

  • \(f_{i, j - 1, k - 1} \leftarrow f_{i - 1, j, k} \times j \times k\)
  • \(f_{i, j - 1 + x, k - 1 + y} \leftarrow f_{i - 1, j, k} \times j \times k \times \frac{1}{x!} \times \frac{1}{y!}\)

第二个式子的形式类似于卷积,我们考虑生成函数。不妨设 \(F_i(x, y) = \sum_j \sum_k f_{i, j, k} x^i y^j\),则

\[F_i(x, y) = \frac{\partial}{\partial x} \frac{\partial}{\partial y} F_{i - 1}(x, y)(1 + (e^x - 1) (e^y - 1)) \]

我们把 \(F_i(x, y)\)\(e^x\) 为底表示出来,即设

\[F_i(x, y) = \sum\limits_j \sum\limits_k g_{i, j, k} e^{jx} e^{ky} \]

那么我们有

\[g_{i, j, k} = g_{i - 1, j, k} \cdot j k - g_{i, j, k - 1} \cdot j (k - 1) - f_{i - 1, j - 1, k} \cdot (j - 1) k + 2f_{i - 1, j - 1, k - 1} \cdot (j - 1) (k - 1) \]

边界为 \(g_{1, 1, 1} = 1\),所求即 \(f_{i, 0, 0} - \sum_j \sum_k g_{i, j, k}\)

于是直接 \(\texttt{dp}\) 即可,时间复杂度 \(\mathcal{O}(n^3)\)

算法二

不需要上面那个结论的做法。

考虑容斥。我们把一个结点的状态分为三种:

  • \(T_1\) 中为叶子,在 \(T_2\) 中为非叶子。
  • \(T_1\) 中为非叶子,在 \(T_2\) 中为叶子。
  • \(T_1, T_2\) 中都为叶子。

那么合法的方案数就是前两种情况的和减去第三种情况的两倍。

\(f_{i, j, k}\) 表示考虑到前 \(i\) 个点,\(T_1\) 前面有 \(j\) 个为非叶子的结点、\(T_2\) 后面有 \(k\) 个为非叶子的结点的方案数,考虑转移。

对于第一种情况,我们有:

\[f_{i, j, k} \leftarrow f_{i - 1, j, k + 1} \times j \times k - f_{i - 1, j, k} \times j \times k \]

对于第二种情况,我们有:

\[f_{i, j, k} \leftarrow f_{i - 1, j - 1, k} \times (j - 1) \times k - f_{i - 1, j, k} \times j \times k \]

边界条件为 \(f_{1, 1, k} = k\),答案为 \(\sum f_{n, j, 1}\)

时间复杂度 \(\mathcal{O}(n^3)\)

众数 \((\texttt{Easy} \ 3/ 3)\)

果然 T2 最可做。

如果我们钦定颜色 \(x, y\),并把选择的区间内的 \(y\) 都变为 \(x\),那么最优方案就是确定的,可以通过一遍最大子段和求出。发现钦定 \(x\) 扫一遍可以对于所有 \(y\) 求出答案,于是我们有了一个 \(\mathcal{O}(n)\) 处理单种颜色的做法。

对于一种颜色 \(x\),我们强制选择的区间 \([l, r]\) 满足:

  • \(l = 1\)\(a_{l - 1} = x\)
  • \(r = n\)\(a_{r + 1} = x\)

这样显然是最优的。设 \(x\)\(a\) 中出现了 \(cnt_x\) 次,那么它会产生 \(\mathcal{O}(cnt_x^2)\) 个查询的区间。

根号分治。对于 \(cnt_x > B\)\(x\),使用第一种方法,时间复杂度 \(\mathcal{O}(\frac{n^2}{B})\)。同时第一种方法也可以求出把选择的区间内的 \(x\) 都变为 \(y\) 的最优方案,所以只用考虑 \(cnt_x \le B\)\(x\) 了。

对于一个查询的区间,我们肯定是要求出区间众数。但是区间众数的出现次数不超过 \(B\),我们把所有的询问挂在右端点上,并把左端点排序,然后扫一遍,设当前处理到的点为 \(i\),考虑维护 \(p_j\) 表示使得 \([l, i]\) 的区间众数出现次数 \(\ge j\) 的最大的 \(l\),然后双指针扫一遍即可实现区间众数的查询,时间复杂度 \(\mathcal{O}(nB)\)

\(B = \sqrt n\),时间复杂度 \(\mathcal{O}(n \sqrt n)\)

简单题 \((\texttt{Medium} \ 3 / 5)\)

有点麻烦的题。

我们发现一个性质:对于一个点双,必然可以选出两个点 \(u, v\),使得除了这两个点,其他点的度数都为 \(2\),即形成了一个类似于灯笼骨架的结构,这东西好像叫杏仁。性质的证明可以用反证法,把多的边设出来,然后找一些等式来推出有边权为 \(0\)

那么,假设我们能够 \(\mathcal{O}(1)\) 算出一个杏仁内部两个点之间的路径数量和权值和,我们就能建出圆方树,然后用倍增什么的维护一下就可以了。

然后对于一个杏仁,设其两个端点为 \(u < v\),它们之间有 \(k\) 条路径,设 \(pre_x\) 表示 \(x\)\(u\) 的距离,\(suf_x\) 表示 \(x\)\(v\) 的距离,\(E\) 为这个点双内所有边权和,选出的两个点为 \(x < y\),我们分类讨论:

  • \(x = u, y = v\), 则路径数量为 \(k\),权值和为 \(E\)
  • 否则,若 \(x = u\),则路径数量为 \(k\),权值和为 \(E + (k - 2) \times suf_y\)\(y = v\) 类似。
  • 否则,若 \(x, y\)\(u \to v\) 的同一条路径上,不妨设 \(pre_x < pre_y\),则方案数为 \(k\),权值和为 \(E + (k - 2) \times (pre_x + suf_y)\)
  • 否则,方案数为 \(2k - 2\),权值和为 \(2E + (k - 3) (pre_x + suf_x + pre_y + suf_y)\)

时间复杂度 \(\mathcal{O}(n \log n)\)代码咕了最裂解了。

面条 \((\texttt{Hard} \ 8 / 6)\)

这就是那种我只能欣赏的题。

算法一

假设每次拉面的时候不减半,最后把答案除以 \(2^k\) 即可。

\(2^t \mid\mid x\),则 \(t + 1\) 次操作以后,面条会变成这个样子:

\[\begin{matrix}\underbrace{a_1\ a_1\ \cdots\ a_1}_{2^{t + 1}}\end{matrix}\ \begin{matrix}\underbrace{a_2\ a_2\ \cdots\ a_2}_{2^{t + 1}}\end{matrix}\ \cdots \ \begin{matrix}\underbrace{a_m\ a_m\ \cdots\ a_m}_{2^t}\end{matrix} \]

所以我们可以先把前 \(t\) 次的情况预处理出来,下面从这种情况开始分析,并把一段用一个数代替。

考虑 \(t + 1\) 次操作之后再进行一次操作会变为什么样子:

\[a_1 + a_m, a_1 + a_{m - 1}, a_2 + a_{m - 1}, a_2 + a_{m - 2}, \cdots \]

它是一个前后配对的,错位的相加。设 \(b_i = a_{i + 1} - a_i\),那么在一次变换之后,它会变为

\[-b_{m - 1}, b_1, -b_{m - 2}, b_2, \cdots \]

考虑序列 \(b_1, b_2, \cdots, b_{m - 1}, -b_{m - 1}, -b_{m - 2}, \cdots, -b_1\),那么上述的变换可以看作是它的一种置换,所以我们可以得到 \(k\) 轮操作之后的差分数组了。

设原序列 \(a\) 的和为 \(s\)、操作之后的差分数组为 \(p\)\(c_i = (m - i) 2^{t + 1} - 2^t\) 为差分数组每一项被计算的次数,操作之后的 \(a_1\) 就是 \(\frac1n \left( s \cdot 2^k - \sum_{i < m} p_i \cdot c_i \right)\)

打个表可以发现这个置换的循环节大小是 \(\mathcal{O}(m)\) 的,于是可以做到 \(\mathcal{O}(n^2 + q)\)

算法二

先不管 \(a_1\)。我们需要求 \(\sum_{i < x} p_i\)。假设置换为 \(g\),所求即

\[\sum\limits_{i} b_i [g^k(i) < x] \]

考虑其逆置换 \(g^{-1}\),所求即 \(\sum_{i < x} b_{g^{-k}(i)}\)。考虑求出 \(g^{-1}\) 的所有置换环,那么对于一个长度为 \(l\) 的置换环,我们可以循环卷积求出 \(c \in [0, l)\) 时的答案。

注意到长度不同的置换环一共有 \(\mathcal{O}(\sqrt n)\) 种,我们可以对于每种长度把答案累加然后依次求和,时间复杂度 \(\mathcal{O}(n \log n + q \sqrt n)\)

算法三

发现一个性质:所有置换环的大小肯定是 \(\varphi(\frac{n}{2^t})\) 的约数,这意味着不同大小的置换环只有 \(\mathcal{O}(d(n))\) 种,并且答案模 \(\varphi(\frac{n}{2^t})\) 是同余的,我们直接处理出每一种余数的答案,就可以 \(\mathcal{O}(1)\) 回答询问了。

时间复杂度 \(\mathcal{O}(n \log n + nd(n) + q)\),记得求 \(2^{-k}\) 用光速幂。

关于实现:由于代码十分冗杂,所以各种错误会很多,待补。

计算几何 \((\texttt{Easy} \ 2 / 0)\)

实际上说 \(\texttt{Easy}\) 也不简单,但是学了半标准杨表之后看这个题就会简单很多很多 /xyx

\(x' = \min\{x, y + z\}\)\(y', z'\) 类似;然后令 \(a = y' + z' - x\)\(b, c\) 类似;然后这个题就变成 这个题 了。即统计有多少个 \(a \times b\) 的矩阵 \(M\) 满足 \(M_{i, j} \in [0, c]\),且每行每列非严格递增。

考虑半标准杨表,它的条件是行非严格递增,列严格递增。我们只需要强制把第 \(i\) 行的数都加上 \(i\),就可以构造一个满足条件的矩阵到 \(a \times b\),值域为 \([1, a + c]\) 的杨表的双射,因为显然不用担心第 \(i\) 行有数小于 \(i\) 或大于 \(c + i\)

那么答案就是

\[ \begin{aligned} & \prod\limits_{i = 1} ^ a \prod\limits_{j = 1} ^ b \frac{a + c + j - i}{a - i + b - j + 1} \\ = & \prod\limits_{i = 1} ^ a \frac{(a + b + c - i)!}{(a + c - i)!} \cdot \frac{(a - i)!}{(a - i + b)!} \end{aligned} \]

时间复杂度 \(\mathcal{O}(Tn)\)

深搜 \((\texttt{Medium} \ 5 / 8)\)

首先把权值离散化,从小到大枚举权值 \(i\),求出所有点对权值 \(\ge i\) 的概率和。

考虑暴力怎么做。把权值 \(< i\) 的点染成白色、\(\ge i\) 的点染成黑色,设 \(f_u\) 表示以 \(u\) 为开始点的所有点对的概率和,\(t_u\) 表示 \(u\) 的子树内是否有白点,\(s_u\) 表示 \(u\) 的所有儿子 \(v\)\(t_v\) 之和。则

\[f_u = [a_u \ge i]\left(1 + \sum\limits_{v} \frac{f_v}{s_u + (1 - t_v)}\right) \]

然后这个 \(\rm dp\) 可以用动态 \(\rm dp\) 优化,再加一个全局平衡二叉树就能做到 \(\mathcal{O}(n \log n)\) 了。

说着不难,但是代码写起来有亿点恶心。

posted @ 2022-05-30 19:31  Scintilla06  阅读(48)  评论(0编辑  收藏  举报