ZJOI2019

麻将 \((\texttt{Medium} \ 4 / 3)\)

高级题。

首先考虑给定一个集合,如果判断它是否有一个子集是胡的。

考虑 \(\rm dp\),设 \(f_{0/1, j, k, p}\) 表示当前是否有一对将,预留了 \(j\)\(\{i - 1, i\}\)\(k\)\(\{i\}\),最多可以选出 \(p\) 对不同的对子的最大面子数量,于是就可以做了。

至于原题,设 \(g_{i, t, \textbf{f}}\) 表示考虑完 \(\le i\) 的麻将,选了 \(t\) 张牌,当前 \(f\) 的状态为 \(\textbf{f}\) 的方案数,然后转移就是按照 \(\textbf{f}\) 的转移。

但是这样的复杂度无法接受。考虑到 \(\textbf{f}\) 的可能的状态较少,可以构建一个自动机,状态即为 \(f\) 数组的状态,\(\Sigma = \{0, 1, 2, 3, 4\}\),然后在自动机上 \(\rm dp\) 即可。

设自动机的状态数为 \(S\),时间复杂度为 \(\mathcal{O}(n^2|S|)\)。一般方法构建自动机的状态数在 \([2 \times 10^3, 6 \times 10^3]\) 之间,不过鱼大把自动机最小化了一手好像能做到 \(|S| = 567\) /jk

线段树 \((\texttt{Easy} \ 3 / 2)\)

题目的意思就是求所有情况下最终 tag\(1\) 的结点个数和。

根据传统,我们在一次 Modify 操作中把所有点分为五类:

  • 会被递归到,且不再继续递归下去的点,即恰好被完全覆盖的点。
  • 会被递归到,且继续递归下去的点。
  • 不会被递归到,且被完全覆盖的点
  • 不会被递归到,但是会被下传懒标记的点。
  • 不会被递归到,也不会被下传懒标记的点。

\(f_u\) 表示答案,\(g_u\) 表示 \(1 \to u\) 的路径上懒标记都为 \(0\) 的期望就可以做了。

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

Minimax 搜索 \((\texttt{Medium} \ 5 / ?)\)

不难发现我们只关注权值和 \(W\) 的相对大小关系,于是可以把 \(< W\) 的数赋为 \(0\)\(= W\) 的赋为 \(1\)\(> W\) 的赋为 \(2\)

首先考虑判定问题。我们可以随意调整集合内的权值,设 \(f_{u, l, r}\) 表示以 \(u\) 为根的子树,最终可能的值域为 \([l, r]\) 的集合数量,其中 \(0 \le l \le r \le 2\),那么就可以 \(\rm dp\) 了,时间复杂度 \(\mathcal{O}(n)\)

考虑对于一个集合,求出最小的代价。我们只需要求出使用 \(k\) 的代价不能使答案变化的方案数 \(g_k\) ,则 \(ans_k = g_k - g_{k - 1}\)

我们把上面的 \(\rm dp\) 加上一维,设 \(f_{u, k, l, r}\) 表示以 \(u\) 为根的子树,代价 \(\le k\),最终可能的值域为 \([l, r]\) 的方案数,那么转移的话在 \(k\) 这一维就是 \(\max\) 卷积,初值再修改一下,其余按照判定的转移即可,时间复杂度 \(\mathcal{O}(n(R - L))\),可以通过 \(70\) 分。

发现 \(k \leftarrow k + 1\) 的时候只会改变 \(\mathcal{O}(1)\) 个叶子的 \(f\),使用 \(\rm ddp\) 可以做到 \(\mathcal{O}(n \log^2 n)\) 的时间复杂度,但是因为 \(l, r\) 两维有 \(6\) 种状态,所以还要带一个 \(36\) 的常数,无法通过。


考虑换一种思路。发现如果确定了代价为 \(k\),那么调整的方案我们可以贪心地取:如果 \(u\)\(W\)\(\rm lca\) 深度为奇数,我们就把 \(u\) 的权值减去 \(W\),否则加上 \(W\)。我们把 \(1 \to W\) 这条链上的所有点删掉,设 \(cnt_u\) 表示 \(u\) 的子树内叶子节点个数,\(f_u\) 表示 \(u\) 的子树内使得 \(u\) 的权值 \(< W\) 的方案数,\(g_u\) 表示使得 \(u\) 的权值 \(> W\) 的方案数。

假设当前结点的深度为奇数,那么有

\[ \begin{cases} f_u = \prod\limits_{v \in son_u} f_v \\ g_u = 2^{cnt_u} - \prod\limits_{v \in son_u} f_v \\ \end{cases} \]

把重儿子单独拿出来,有

\[g_u = 2^{cnt_u} + \left(- \prod\limits_{v \in son_u, v \ne mson_u} f_v\right) \times f_{mson_u} \]

这是一个 \(a_i = b + ka_{i + 1}\) 的形式,具有结合律,于是就可以做了。

维护轻儿子积的时候需要记录 \(0\) 的个数。

代码待补。

开关 \((\texttt{Hard} \ 7 / 0)\)

真的神仙题,不知道怎么想到的。

算法一

首先把初始状态和目标状态换一下,用一个集合表示当前状态中为 \(1\) 的位置,并不妨设 \(\sum p_i = 1\)

\(E_{T}\) 表示从状态 \(T\) 到状态 \(\varnothing\) 状态,即目标状态的期望步数,则 \(E_{\varnothing} = 0\);对于 \(T \ne \varnothing\),我们有

\[E_T = 1 + \sum\limits_{i = 1} ^ n p_i E_{T \oplus \{e_i\}} \]

其中 \(\oplus\) 表示集合的异或。

这样我们得到了 \(2^n\) 个方程,直接做是 \(\mathcal{O}(2^{3n})\) 的。

这个方程可以手解。事实上,这个方程的解是

\[E_T = \sum\limits_{S} [|S \cap T| \equiv 1 (\bmod \ 2)] w(S) \]

其中

\[w(S) = \left( \sum\limits_{x \in S} p_x \right) ^ {-1} \]

证明:显然 \(T = \varnothing\) 时成立,\(T \ne \varnothing\) 时,设:

\[ \begin{aligned} F & = 1 + \sum\limits_{i = 1} ^ n p_i E_{T \oplus \{i\}} - E_T \\ & = 1 + \sum\limits_{i = 1} ^ n p_i (E_T - E_{T \oplus \{i\}}) \end{aligned} \]

我们只需证明 \(F = 0\)。考虑每个非空集合 \(S\)\(F\) 的贡献:若 \(i \in S\),则 \(p_i (E_T - E_{T \oplus \{i\}}) w(S)\) 的贡献为 \(p_i (-1)^{|S \cap T|}\),合起来就是 \((-1)\);否则贡献为 \(0\)

所以

\[F = 1 + \sum\limits_{S \ne \varnothing} (-1) ^ {|S \cap T|} \]

容易证明,\(T \ne \varnothing\) 时有 \(F = 0\)

所以上述的构造是正确的。而对于初始集合 \(T\),我们有

\[|S \cap T| = \sum\limits_{x \in S} s_x \]

发现 \(\sum p_i \le 5 \times 10^4\),所以可以通过简单背包求出答案,时间复杂度 \(\mathcal{O}(n\sum p_i)\)

算法二

算法一太神了,让我们尝试从正面推导。

依然设 \(\sum p_i = 1\)

考虑容斥:设 \(f_i\) 表示 \(i\) 步以后恰好合法的概率,\(g_i\) 表示 \(i\) 步以后合法的概率,\(h_i\) 表示 \(i\) 步以后回到当前状态的概率,则有

\[f_i = g_i - \sum\limits_{j < i} f_j h_{i - j} \]

我们设 \(F, G, H\) 表示三者的概率型生成函数,上面的等式就变成了

\[ \begin{aligned} F(x) & = G(x) - F(x)(H(x) - 1) \\ \Leftrightarrow F(x) & = \frac{G(x)}{H(x)} \end{aligned} \]

但是直接求 \(G, H\) 较为麻烦,我们发现可以求出 \(g, h\) 的指数型生成函数。具体地:

\[ \begin{cases} \widehat{G}(x) = \frac{1}{2^n} \prod\limits_{i = 1} ^ n (e^{p_ix} + (-1)^{s_i} e^{-p_ix}) \\ \widehat{H}(x) = \frac{1}{2^n} \prod\limits_{i = 1} ^ n (e^{p_ix} + e^{-p_ix}) \\ \end{cases} \]

所以二者的 \(\rm EGF\) 展开后都形如 \(\sum_i a_ie^{ix}\),而对于 \(\rm PGF\),我们只需要把 \(\rm EGF\) 除掉的 \(n!\) 乘回去,即

\[\widehat{\lambda}(x) = ae^{bx} = a\sum\limits_{i} \frac{b^ix^i}{i!} \to \lambda(x) = \frac{a}{1 - bx} \]

所以我们可以设 \(G(x) = \sum_i \frac{u_i}{1 - ix}, H(x) = \sum_i \frac{v_i}{1 - ix}\)

\(\sum p_i\) 较小,我们可以通过 \(\rm dp\) 得出各项系数,所以我们就可以通过

\[F'(x) = \frac{G'(x)H(x) - G(x)H'(x)}{H^2(x)} \]

求出答案了。

但很遗憾——这样做是错误的。因为当 \(b = 1\) 时,\(1 - bx = 0\),上式就没有意义了。

所以我们可以给分子分母同乘 \(1 - x\),此时 \(G, H\) 均收敛,那么

\[G(x) = u_1 + \sum\limits_{i \ne 1} \frac{u_i(1 - x)}{1 - ix} \]

\[G'(x) = \sum\limits_{i \ne 1} \frac{u_i(i - 1)}{(1 - ix)^2} \]

于是可以得到

\[F'(1) = \sum\limits_{i \ne 1} \frac{u_iv_1 - u_1v_i}{(i - 1)v_i^2} \]

可以直接计算了。时间复杂度 \(\mathcal{O}(n \sum p_i)\)

语言 \((\texttt{Easy} \ 3 / 2)\)

果然还是第二题最可做。

发现对于固定的 \(u\),合法的 \(v\) 构成了一棵连通子树,此处我们假设 \((u, u)\) 也合法,考虑维护这棵连通子树。

一种方法是树剖加上扫描线那样的线段树,这样就是 \(\mathcal{O}(n \log^2 n)\)

发现我们只需要把过 \(u\) 的所有链的端点按照 \(\rm dfn\) 顺序排成一圈,两两距离和除以 \(2\) 再加上 \(1\) 就是点数,所以我们可以直接用线段树合并维护过 \(u\) 的链的端点,加上 \(\mathcal{O}(1) \ \texttt{LCA}\) 可以把时间复杂度降至 \(\mathcal{O}(n \log n)\)

代码也十分好写。但是数据中存在 \(s_i = t_i\) 的情况,需要注意。

浙江省选 \((\texttt{Medium} \ 3 / 6)\)

考虑 \(m = 1\) 的情况,发现求一个半平面交就可以了。

考虑 \(m = 2\) 的情况,此时我们要求最高排名为 \(2\) 的人,可以想到先把最高排名为 \(1\) 的人去掉,然后再求一遍半平面交,只要判断每条直线在半平面交所占的区间上是否存在一个点 \(x_0\),使得 \(x = x_0\) 时排名第 \(2\)

于是我们求 \(m\) 次半平面交可以解决问题,考虑如何判定。发现一条被删掉的直线在半平面交上方肯定是一段区间,我们只需要把所有的区间求出来,差分以后排序扫一遍,就可以 \(\mathcal{O}(n)\) 实现一次判定了。

实现时需要注意的地方:

  • 本题中 \(x\) 必须是自然数,所以在判断交点还有找 \(x_0\) 的时候需要注意取整。
  • 排名的定义是使得 \(f_j(x_0) > f_i(x_0)\)\(j\) 的个数 \(+1\),所以多条直线共点,甚至在半平面交上都只占一个点的情况也要考虑进去。
  • 其他计算几何老生常谈的问题,比如手写分数类、直线的平行等。
posted @ 2022-03-23 20:22  Scintilla06  阅读(30)  评论(1编辑  收藏  举报