The 2020 ICPC Asia Macau Regional Contest

A - Accelerator

设加速器序列为 \(a_1, a_2, \cdots, a_n\),那么考虑把题目里的式子展开:\(a_n+a_na_{n-1}+a_na_{n-1}a_{n-2}+\cdots + \prod_{i=1}^n a_i\)

我们把它一项项考虑。对于第 \(k\) 项,如果枚举过所有 \(n!\) 种情况,那就是对下标集合 \(\{1, 2, 3, \cdots, n-1, n\}\) 选出一个长为 \(k\) 的排列 \(a_{p_1}, a_{p_2}, \cdots, a_{p_n}\)。而每个 \(p\) 都有若干次贡献,但我们最终要求期望,这个东西最终要被除掉,所有可以不考虑。

简化一下式子,就是:

\[\frac{\sum\limits_{S\subseteq \{1, 2, \cdots, n\}, |S|=k} \prod_{i\in S} a_i k!}{{n\choose k}k!} = \frac{\sum\limits_{S\subseteq \{1, 2, \cdots, n\}, |S|=k} \prod_{i\in S} a_i}{{n\choose k}} \]

分子上的东西实际上就是 \([x^k]\prod_{i=1}^n (1+a_ix)\)。答案就是 \(\forall k\in \{1, 2, \cdots, n\}\) 求个和。分治 FFT 即可,复杂度 \(O(n\log^2 n)\)​。

B - Boring Problem

真搞死我了这个题。特意学习了一下这种题目的一些解法,好像是什么套路?

像这种往后面随机加字符,出现给定字符串集合的任意一个后停止,问期望长度的,主流做法有两种:PGF 和 AC 自动机。但是这题有钦定前缀,PGF 很不好处理,而对于 AC 自动机而言就只要跑一遍就行了,因此我们考虑后者。

首先朴素的思想是,对 \(T_{1\sim n}\) 建立 AC 自动机。然后对每个结点构造方程,最后高斯消元,复杂度 \(O(n^3m^3)\),无法通过。考虑把方程的数量降下来。

注意到一个关键性质:对于 Trie 图中每个点,连出的所有非树边的 Trie 树深度都小于当前点。而且这个性质是一般图跑了一个 DFS 生成树所不具备的。

对 Trie 树做树链剖分(任意选择重儿子),可以发现虽然 Trie 树是 \(O(nm)\)​​ 的,但由于只有 \(n\)​ 个串,链只有 \(n\)​​​ 条。将作为链顶的点设为关键点,并尝试用这些关键点表出其他的点。

先写出朴素的方程:\(E(x)= 1+\sum_{c\in \Sigma} E(\textit{next}_{x,c})\times p_c\)​。我们把重儿子 \(y\)​ 移项(记 \(x\to y\)​ 对应字符为 \(c'\)​),得:\(E(y)=\frac{1}{p_c}(E(x) - \sum_{c \in \Sigma, c \ne c'} E(\textit{next}_{x,c})\times p_c - 1)\)​。根据上面的性质,我们自根向下表示,那么对于 \(y\) 而言,\(E(y)\)\(y\) 的父亲和兄弟相关。父亲以及兄弟中的“根据 fail 指针补上的边”都是深度浅于 \(y\) 的,都已被表示而可以直接叠加,其他的兄弟必然都是链顶可以直接代入。

现在每个点都有一个关于链顶的等式,我们选出 \(n\)​ 个叶子,利用叶子的期望等于 0 建立 \(n\) 个方程,\(O(n^3)\)​ 高消即可。最后带入等式可以得到所有点的期望。

最后把 \(R\) 放 AC 自动机上跑一遍即可,注意特判叶子。复杂度 \(O(n^3+n^2mk+|R|)\)

C - Club Assignment

从这个角度看问题:每次我们钦定一对点 \(u, v\) 不在同一个 club 里。不难发现一定是在所有关系 \((i, j)\) 二元组中找其中若干个 \(w_i\oplus w_j\) 最小的,越多越好,直到找到一个发现关系冲突了为止。之所以要找最小的,是因为如果我们跳过了一些小的,那这些小的就不得不成为答案(参考 MEX)。

再观察,发现我们只要使这些关系构成一颗树(最小异或生成树)即可,原因是我们不必等到出现冲突,也不用管是不是没有成树就出现了冲突,答案方案就已经固定。对于一个固定的方案,我们可以通过 01-Trie 求解答案。

而求异或最小生成树是个套路问题了。每次按某一位(从高位到低位枚举)分治,然后借助 01-Trie 找到联立两个点集的最小边即可。总复杂度 \(O(n\log^2 w)\)

D - Artifacts

阅读理解题。几个实现技巧:

  • getline 读入整行;
  • std::string 中的 find 函数可以识别类别;
  • sscanf 读取数字。

F - Fixing Networks

考虑最省顶点的方式,就是构造 \((d+1)\) 个点的完全图,用以应付一个 department。最后只需要考虑 \(c=1\) 的情况了。

考虑如下构造:将 \(n\) 个点排成环,每个点向两侧相邻的 \(\lfloor d/2\rfloor\) 个点连边。如果 \(d\) 为奇数就向对面再连边。如果 \(n\) 是奇数使得没有对面的点,那说明无解,因为这样整张图的度数和就是奇数了。

注意特判 \(d=0,1\),以及点数不够用的情况(\(c(d+1)>n\))。

G - Game on Sequence

一开始有一个比较怪的想法,就是每次 push back 后,从后往前暴力按必胜必败态定理更新,再加一个如果对当前考虑的点不起作用就跳过。但是感觉不好操作也没啥前途就先弃了。

其实有更优秀的解法:记 \(s_i\)\(i\) 这个位置先手是否必胜。

考虑一个关键性质:对于出现超过一次的 \(x\),选取 \(A_i=A_j=x\)\(i<j\) 的一对 \((i,j)\)。讨论一下 \(s_j\)

  • 如果 \(s_j = 0\),那么显然 \(s_i = 1\)
  • 如果 \(s_j = 1\),那么由于 \(j\) 可以到达的点中存在一个 \(s=0\) 的,而 \(i\) 可以到达 \(j\) 可达的所有位置,那么 \(s_i\) 仍然 \(= 0\)

也就是说,如果询问一个 \(k\),满足 \(A_k\) 不是最后一次出现的,那么 \(s_k=1\)。如果是最后一次出现的,我们可以暴力维护 dp 去应付这种询问。对一个点暴力 dp 复杂度是 \(O(\log A)\),每次 push back 要对所有 \(A\) 都做一遍(这里注意顺序)。

总复杂度 \(O(nA\log A)\)​。

I - Nim Cheater

根据博弈论基础知识(SG 定理),Nim 游戏的后手必胜充要条件是,所有石子堆的石子个数异或起来的结果为 \(0\)。那转化后的题意就是,对于每次修改操作后,选出一个总花费最大的集合,满足集合中元素的权值异或和为 \(0\)。修改操作有添加一个元素,以及撤销。

下面记 \(U=2^{14}=16384\)。一个显然的 dp 是:\(f(u)\) 表示选取的异或和为 \(u\),最大花费和是多少。每当加入一个元素,就可以在 \(O(U)\) 时间内更新 \(f\)

由于只有添加和撤销操作,不难发现操作构成一棵树形结构。建树后跑 DFS,对每个点都计算一边 dp 数组。直接这样做是 \(O(U\times n)\) 的时空复杂度,然而空间限制只有 8 MB,无法通过。

题解提供了一个优秀的想法:由于 DFS 的顺序并不影响结果,考虑轻重链剖分。对于每个点,我们先计算轻儿子,并将 \(f\)​ 数组复制;最后计算重儿子是直接继承 \(f\)​ 数组。得益于一棵树上每个点到根的路径上都只有不超过 \(O(\log n)\)​ 条轻边,那么一个点实际上只要保留 \(O(U\log n)\)​ 大小的祖先上的信息。

J - Jewel Grab

转化询问:对于一个询问 \(s, k\),找到一个最长的区间 \([s,t]\),满足区间中出现次数超过一次的元素的,出现次数减一,的和,不超过 \(k\)。然后对于所有区间中出现次数超过一次的元素,找出其中权值最大的求和;对其他的元素直接求和。计算最终结果。

如果“出现次数”、“区间”相关的题目做多了,不难反应到,定义一个 \(\textit{last}_i\) 表示位置 \(i\) 的元素在序列中上一次出现的位置(第一次出现则 \(\textit{last}_i = 0\))。那么上述的 \(t\) 就是最大的一个整数,满足 \(\sum_{i=s}^t [\textit{last}_i < s] \le k\)

抓住 \(k\le 10\),即 \(k\) 很小这个特点。考虑我们可以暴力找出所有 \(last_i<s\) 的这些 \(i\),具体的,建立线段树,维护区间 \(\textit{last}\) 的最小值,然后一次线段树上二分即可找到一个 \(\textit{last}_i < s\) 的最近的 \(i\)。如此往复 \(O(k\log n)\) 可以完成所有这样位置的搜寻。

然后我们实现统计答案:求出 \([s, t]\) 的权值和,然后减掉出现次数超过一次的,但不是最大的元素的权值。这里要减去的只有 \(O(k)\) 个。

最后修改是非常简单的事情,复杂度 \(O(mk\log n)\)

K - Candy Ads

没写,口胡一下。可以说非常明显的 2-SAT 了,将时间看做一维,三维空间下相交说明两者二选一,以及 \(m\) 个额外限制也是 2-SAT 量身定制。

一开始想了一个比较繁琐的线段树优化建图做法,然后发现四百万乘上 \(\log\)​ 的时间有点卡,就不管了。

结果发现这玩意可以跑 bitset!(事实上这种很多维度的东西都可以想想这个?)考虑最终我们用 bitset 去维护整个 \(O(n^2)\) 大小的邻接矩阵,然后用 Kosaraju 算法在上面跑。

建图时就体现 bitset 的优越之处了。我们考虑有,两者相交,当且仅当 \(x\) 方向相交 \(\land\) \(y\) 方向相交 \(\land\) 时间区间相交。三维的信息我们做三次(或六次)就行了。时间复杂度差不多是 \(O(n^2/w + m)\)

为什么我不写呢?因为这题空间只有 512 MB,所以要分块处理,实在有点麻烦,不想写了。

L - Random Permutation

从排列的角度考虑问题:对于一个排列 \(p\),有多少合法的 \(a\)?显然是 \(n!\)。而所有 \(n!\) 种排列都对应 \(n!\)\(a\),那么答案就是 \((n!)^2/n^n\)

然而我傻掉了,使用找规律通过了此题。

posted @ 2021-09-26 20:01  -Wallace-  阅读(1388)  评论(2编辑  收藏  举报