2022 百度之星 复赛
5/6,进决赛了,不过因为罚时比较垃圾,rk50,可能要自费了。
A 子序列
显然把每个数单独作为一个上升子序列答案是最大的,答案就是 \(\sum a_i\) 。
B 分组
做一个树形背包,设 \(dp(x,i,j)\) 表示将子树 \(x\) 分组,并且 \(x\) 所在的组有 \(i\) 个点,组内到 \(x\) 距离最远为 \(j\) 的方案数,dfs 时不断合并 \(x\) 与它的儿子 \(y\) 的 dp 数组即可。
C 最大值
经过简单的推导不难发现答案是 \(n\sum_{i=1}^m i^{n-1}\) ,由于 \(n\times m\le 10^{12}\) ,说明 \(n,m\) 必有一者 \(\le 10^6\) 。
若 \(m\le n\) ,直接用快速幂暴力计算即可。若 \(n\le m\) ,则是经典的自然数幂和问题,用拉格朗日插值,第二类斯特林数,伯努利数均可解决。
D 子序列 2
将所有询问离线下来按照 \(k\) 从小到大依次处理,则等价于维护一个 01 序列,每次需要回答一个区间内 01 交错的子序列数目。
用一棵线段树维护这个序列,每个节点维护 \(v[x][y]\) 表示从这个区间内以 \(x\) 为第一个元素,以 \(y\) 为最后一个元素的 01 交错子序列数目即可。
E 项链
首先根据 Polya 引理,答案就是 \(g(n)=\frac 1 n (f * \varphi)(n)\) ,其中 \(f(m)\) 表示不考虑循环同构,长度为 \(m\) 的环的答案,* 表示狄利克雷卷积。
那么我们需要对每个 \(m\) 求出 \(f(m)\) ,考虑用所有串的数目减去不是好串的数目,相当于在 AC 自动机上跳且不经过某些节点。构造出这个
AC 自动机对应的转移矩阵 A,由于结构是一个环,所以起点和终点必须相同,即求 \(trace(A^m)\) 。直接做时间复杂度 \(O(n|S|^3)\) ,无法通过。
注意到我们每次只需要求 \(trace\) ,即矩阵对角线上的 \(n\) 个元素,于是可以取 \(k=\sqrt n\) ,预处理出 \(A^0,A^1,\dots,A^{k-1}\) 与 \(A^k,A^{2k},\dots,A^{n}\) 这 \(O(k)\) 个矩阵,每次需要求 \(trace(A^m)\) 时,将其拆成两个已经预处理过的矩阵之积,只计算对角线上的 \(|S|\) 个元素,于是求出所有 \(f(m)\) 的时间复杂度被优化至 \(O(k|S|^3+n|S|^2)\)。
另外还需要注意当 \(m\) 比较小的时候,不能将长度 \(>m\) 的串扔进 AC 自动机里,于是对于 \(m\le 50\) 的部分需要暴力重构 AC 自动机去算 \(f(m)\) 。
最后再对 \(\varphi\) 反演一下即可算出所有 \(g(n)\) 。
F 字符串
对反串建后缀自动机与 parent 树,则两个后缀的 lcp 长度就等于它们各自对应的两个点的 LCA 的 len 。
考虑对于一次询问 \([l,r]\) 如何求出答案,我们可以在 parent 树上找出所有 len 大于等于 k ,而其父亲的 len 小于 k 的点,这些点对应了若干个不相交的子树。
那么对于所有的 \(2^{r-l+1}\) 种情况,只有所有被选出的节点都分布在同一个子树中时才有贡献,此时通过统计每个子树中有多少个 \([l,r]\) 内的点不难算出答案。
现在要回答所有的 \(m\) 个询问,使用莫队处理,在添加或删除点时更新每个子树中含有的 \([l,r]\) 的点的数目,并更新答案即可。