「NOI 2021」题解

代码托管到第三方平台上。

NOI2021 题解

D1T1 轻重边

水题

D1T2 路径交点

卡常的水题

考虑 \(k=2\) 的情况,每种路径方案都可以使用一个排列来描述,排列的逆序对数量就可以用来描述交点数。

因此,设矩阵 \(M\in R^{n_1\times n_1},M_{ij}=[(i,j)\in E]\)​​,那么自然而然地得到 \(k=2\) 时答案为:

\[\det(M)=\sum_{p}(-1)^{\sigma(p)}\prod_{j=1}^{n_1}M_{j,p_j} \]

考虑 \(n\)​ 相等的情况。由于 \(k>2\)​ 时,各层的逆序对为叠加关系,因此各层的行列式乘法时 \(-1\)​​​​​ 的指数就会相加,满足系数要求;同时,将行列式相乘也相当于枚举了每一种可能的方案,因此可以得到答案:

\[\prod_{j=1}^{k-1}\det(M_j)=\det(\prod_{j=1}^{k-1}M_j) \]

最后考虑 \(n\)​ 不相等的情况,根据 \(n_k=n_1\)​ 的限制不难想到 \(\det(\prod_{j=1}^{k-1}M_j)\)​ 就是答案。顺向思考,考虑任意一种路径方案,必然可以被描述为:首先,从 \(2\sim k-1\) 的每一层中选择一个大小为 \(n_1\) 的子集,接着就化归到了 \(n\) 相等的情况,最终我们需要对所有的子集方案求和;可以发现这就是 Cauchy-Binet 公式的形式,因此我们的猜想是正确的。

本题有亿点卡常,不建议写成矩阵乘法,建议写成类似于 DP 的形式,最终复杂度即为 \(O(Tn_1\sum m)\)

D1T3 庆典

还不错的题目。

简单转化:题目中“可能经过 \(u\)”等价于“既能从 \(s\) 到达 \(u\),也能从 \(u\) 到达 \(t\)”。

首先考虑 \(m=n-1\)​​ 的部分分,不难论证得出此时图的形态必然是一棵外向树。对于普通的点,它们仅能从祖先的点到达,仅能到达子树内的点。而题目给出的 \(k\) 条边仅仅会影响 \(2k\) 个点的可达性与到达性,其余的点的可达性、到达性仍然可以”借用“祖先的点和子树的点来描述。

这样,我们不难想到,最终可以经过的点就可以被描述为 \(2(k+1)\)​ 个关键点之间的某些链的并集。合法的链即”从 \(s\) 可以到达链头,且从链尾可以到达 \(t\) 的链“。注意到 \(k\) 很小,因此可以暴力 Floyd 求出传递闭包,接着枚举每条链,最后做一个树上链并即可。

还需要注意,新加入的 \(k\)​ 条边也可以被算作合法的链,但是显然这样的链只有端点有效,因此打一下标记即可。

最后解决 \(m\not=n-1\)​ 的情况,将强连通分量缩点之后,题目的性质在新图上仍然满足,缩点后直接跑。

小结:注意图的形态,缩点后保持树形注意答案的形态,一定是链并

复杂度可以做到 \(O(n\log_2n+qk^3)\)

D2T1 量子通信

不错的乱搞题目,正好戳中我的痛点。

由于 \(k\le 15\)​,因此有变化的部分会很少;同时,如果我们将一个单词划分为 \(16\)​ 段,每段长度即为 \(16\)​,那么 \(k\)​ 次修改最多会带来 \(15\)​​ 段变化,也即,必然会有一段保持不变。因此对于询问串,我们可以枚举保持不变的一段,并检查在枚举段相同的单词中是否有差异不超过 \(k\) 的单词。

由于字典中的单词随机,因此每一段中,某种情况的单词期望个数为 \(\frac{4\times10^5}{2^{16}}\approx 8\);此外,计算差异数可以用 __builtin_popcountll 做到 4 次运算,因而复杂度为 \(O(n+q)\),其中 \(n\) 的常数约为 64, \(q\) 的常数约为 512。

小结:一定要多多注意小数据的处理方式,在这道题中就根据较小的修改次数和较长的长度,运用鸽巢原理大幅缩减所需检查的字符串的数量(这应该是查找类题目的重要思路)。

D2T2 密码箱

容易发现 \(f\)​ 计算的是一个连分数:\([a_0;a_1,a_2,\dots,a_n]\)​​

考虑递推计算,设 \(f_k=[a_k;a_{k+1},a_{k+2},\dots,a_n]=\frac{p_k}{q_k}\)​​;特别地,边界 \(f_n=\frac{1}{a_n}\)​​。

那么递推关系为:

\[f_k=a_k+\frac{1}{f_{k+1}} \]

也即:

\[\begin{aligned} p_k&=q_{k+1}+p_{k+1}a_k\\ q_k&=p_{k+1} \end{aligned} \]

这组递推式有两个作用:

第一,根据递推式可以发现 \(\gcd(p_k,q_k)=\gcd(p_{k+1},q_{k+1})\),在边界处 \(\gcd(p_k,q_k)=1\),因此中途结果均保持既约性质,不需要约分;

第二,递推式是线性的,这表明递推过程可以用矩阵来描述;设 \(F_k=\begin{bmatrix}p_k\\q_k\end{bmatrix},M_k=\begin{bmatrix}a_k&1\\1&0\end{bmatrix}\),则 \(F_k=M_kF_{k+1}\)

注意到这个转移与 \(a\)​​​ 相关,而为了维护操作序列的变化,我们最好是将 WE 直接用矩阵来描述。

容易发现 W 其实就是矩阵 \(\begin{bmatrix}1&0\\1&1\end{bmatrix}\);而考虑 E 操作,当 \(a\) 的最后一个元素不为 1 的时候,E 等价于矩阵 \(\begin{bmatrix}1&0\\-1&1\end{bmatrix}\begin{bmatrix}1&1\\1&0\end{bmatrix}\begin{bmatrix}1&1\\1&0\end{bmatrix}\),而当 \(a\) 的最后一个元素为 1 的时候,这个矩阵乘上以后得到 \(\begin{bmatrix}1&1\\1&0\end{bmatrix}\begin{bmatrix}1&0\\-1&1\end{bmatrix}\begin{bmatrix}1&1\\1&0\end{bmatrix}\begin{bmatrix}1&1\\1&0\end{bmatrix}=\begin{bmatrix}1&0\\1&1\end{bmatrix}\begin{bmatrix}1&1\\1&0\end{bmatrix}\),施加上以后恰好等价于“先去掉最后一个元素,再给最后一个元素 +1,再在末尾添加一个 1”,也就是给倒数第二个元素 +1。

因此直接用平衡树维护矩阵积即可,细节有亿点多。

小结:从部分情况入手,逐步推广的思路很好用;尤其是在本题中,E 的操作看起来构造性很强,其实也暗示它很有可能就是某一特殊情况简单推广后的结果。

D2T3 机器人游戏

非常棒的题目,质量很不错

样例 2 的解释贴心地给出了容斥计算的解释,直接模拟可以得到一个 \(O(2^nn^2m)\)​​ 或者 \(O(2^nnm)\)​​ 的容斥做法,这里就不详细解释了。

但是这个做法还需要优化。不难发现对于每个格子的四种操作:不变/赋 0/赋 1/取反 构成了一个群,以下我们分别用 0/1/2/3 表示这四种操作。

我们只需要考虑每个格子被操作覆盖的情况即可计算出方案数。在较差的复杂度中,我们可以直接预处理每种情况的方案数;为了优化,我们需要细致分析。假如一个格子同时被 0,3 覆盖,或者同时被 1,2 覆盖,那么它只能输入输出都为空,因此方案数为 1;假如一个格子被 0/3 其一覆盖,同时被 1/2 其一覆盖,那么它除空外只有一种方案,因此方案数为 2;在其它情况下,方案数均为 3。

需要注意,如果某个格子并未被容斥集合中出发的每机器人次覆盖住,那么该格子便隐式地被 0 覆盖。

那么,对于任意容斥集合 \(P\)​,使用 unsigned 我们不难处理出操作 \(o\)​ 影响到的格子的集合 \(f_{P,o}\)​​,按照上面的分析处理出不同情况的位置集合计算即可。

如此我们得到了 \(O(2^nm)\) 的容斥。


为了方便描述,设 \(r_j\) 表示机器人 \(j\) 影响到的格子个数,也即字符串中 R 数量 +1。

注意到极限数据为 \(n=32\)​​​,恰好为 \(16\)​​ 的两倍,这启示我们折半处理容斥集合。对于仅包含左边 \(16\)​​ 个位置的容斥集合,我们可以直接枚举并计算;对于包含右边 \(16\)​​​ 个位置中任意一个的容斥集合,我们注意到此时贡献非 1 方案数的机器人必然满足 \(r_j\le n-\max P\le \frac{n}{2}\),其中 \(P\subseteq \{0,1,2,\dots,n-1\},\exist p\ge \frac{n}{2},p\in P\)​​​​。

由于每个位置仅会受前 \(r_j\)​​​ 个位置影响,因此我们可以枚举 \(P\)​​​ 中最大值后直接 DP,状态 \(f_{i,S,0/1}\)​​ 表示前 \(i\)​ 个位置,其中 \([i-\frac{n}{2}+1,i]\)​ 的选择情况为 \(S\)​,在 \([0,i-\frac{n}{2}]\)​ 中无/有选中的位置的情况下,容斥的结果。其中每个位置的贡献也可以预处理,\(c_{S,0/1,k}\)​ 表示对于某一位置,若 \([i-\frac{n}{2}+1,i]\)​ 的选择情况为 \(S\)​​​,在范围外无/有选中的位置的情况下,所有 \(r_j\le k\)​ 的机器人的贡献。

DP 结束后还需要计算最大值之外的位置的贡献,用好 \(c\) 即可。

这部分复杂度为 \(O(m2^{\frac{n}{2}}+n^22^{\frac{n}{2}})\)


将两个做法结合在一起即可得到正解。

小结:在降低复杂度的过程中,精细的分析是很有必要的,有时候需要借助比较暴力的预处理,不过在本题中仍需要进一步分析;此外,本题的复杂度平衡依托于当包含的元素都靠前时,容斥集合包含的位置较少;当包含的元素靠后时,有效的机器人 \(r\) 较小,出现这样的 \(\min\)​ 限制的时候需要注意是否可以平衡复杂度。

posted @ 2021-08-05 18:49  crashed  阅读(513)  评论(0编辑  收藏  举报