Cry_For_theMoon  

好困。

1. Permutation

式子就是很平凡的啊,枚举第 \(i\) 位是第一个不同的位置,然后设 \(c_j\)\([i,n]\)\(j\) 的个数,则答案加上:\((\sum_{j\lt a_i}c_j)\times \frac{(n-i)!}{\prod c_k}\)

注意到右边这个东西整体一定是整数(不取模的情况下),因为它有其组合意义。

此时我们可以支持在 \(O(\log mod)\) 或者 \(O(\log^2 mod)\) 的时间内做乘法/除法运算,具体而言有两种实现:

  • 将所有数分解质因子,然后修改的时候在指数上修改,这样需要动态开点 seg。

  • 将模数分解质因子,然后任何数都能表示成 \(rest\times\prod p_i^{a_i}\) 的形式,对于 \(\log mod\)\(p\) 我们修改质数,余项由于和 \(mod\) 互质所以存在逆元 \(rest^{\phi(mod)-1}\)

记录

2. Crash 的文明世界

  • Solution 1

\(\sum_{j}d(i,j)^k\)

也就是求 \(\sum_{j}\sum_{l}S(k,l)\times d(i,j)^{\underline{l}}\)

也就是 \(\sum_{j}\sum_{l}S(k,l)\times \dbinom{d(i,j)}{l}\times l!\)

这里替换的目的是因为组合数往往可以利用递推式的特性去和 dp 结合起来;我们可能会发现第二类斯特林数也具有递推式,但是显然变化量的是 \(d\) 而斯特林的两个指标全不涉及 \(d\)

交换和式 \(\sum_{l}\sum_{j}S(k,l)\times\dbinom{d(i,j)}{l}\times l!\),这是常见的手法。

\(=\sum_{l}S(k,l)\times l!\sum_{j}\dbinom{d}{l}\)

所以我们设 \(f(i,k)\) 表示所有的 \(\dbinom{dis}{k}\) 之和即可。

考虑换根,于是设 \(f(i,k)\) 表示所有子树的点到 \(i\) 的这个东西。

则由于 \(\dbinom{dis}{k}=\dbinom{dis-1}{k}+\dbinom{dis-1}{k-1}\),我们会得到 \(f(u,k)=\sum f(v,k)+f(v,k-1)\)

显然是可以换根计算的,时间复杂度 \(O(nk)\)

记录

  • Solution 2

考虑无脑点分,现在问题变成了统计所有经过 \(rt\) 的路径的答案。

设长度为 \(len\) 的路径贡献为 \(d_len\),这里 \(d_x=x^k\),然后深度为 \(x\) 的点有 \(cnt_x\) 个,则对于点 \(u\),其加上的贡献为:

\[\sum_{len\ge depth_u}d_{len}\times cnt_{len-depth_u} \]

这是差卷积的形式,一次 FFT 解决。

然后再去掉两个点都在一颗子树的情况,这个是类似的,每颗子树内部卷一次。

时间复杂度 \(O(n\log^2 n)\)

懒得写了。

3. Do Use Hexagon Grid 2

我们来研究两个点 \(dis(i,j)\) 的计算。

不难发现 \(dis(i,j)\ge \max\{dx,dy\}\),也就是至少是切比雪夫距离,因为两个维度的增量大小都是不超过 \(1\) 的。

发现若 \(x_i\gt x_j\)\(y_i\lt y_j\) 那么 \(dis(i,j)\) 变为曼哈顿距离;\(x_i\lt x_j\)\(y_i\gt y_j\) 同理;否则就是切比雪夫距离。

由于 \(\max\{dx,dy\}\le dx+dy\) 所以一个必要条件是两两切比雪夫距离不超过 \(D\),然后只要再保证部分点对的曼哈顿距离不超过 \(D\)

第一个约束我们只需要枚举 \(x,y\) 最小的两个点然后就能框选出一个范围,这个范围内的点两两切比雪夫距离都是合法的。

考虑曼哈顿距离这个问题,我们按照 \(x\) 降序排序,则曼哈顿距离变成了 \(x_i-x_j+y_j-y_i\)(不难发现我们不用真的让 \(y_j\gt y_i\),如果它不成立则这个式子也是小于等于 \(D\) 的。)也就是 \((x_i-y_i)-(x_j-y_j)\),所以我们只关注先前选的所有点中 \(x-y\) 最小的点即可。

这导引出了一个 \(O(n^2)\) 的 dp,时间复杂度 \(O(n^4)\),加一些边界剪枝效率就很快了。

记录

4. Access Levels

考虑若 \((i,j)\) 两个文档不在一起则说明既出现了 \(10\) 又出现了 \(01\),反之就是说 \(i,j\) 可以在一起。

而且如果他们两个此时真的在一起则我们可以确定它们的大小关系,特例是两个文档完全相同。

然后就连边形成 DAG,求最小链覆盖,直接匈牙利就 \(O(m^3+m^2n)\) 了。

记录

5. TEST_68

PKUSC D2T2 同 trick 题。

考虑去掉“子树外”这个限制,我们找到一组全局最优解 \((x,y)\),则只有 \(1\rightarrow x,1\rightarrow y\) 这两条路径上的答案不是 \(a_x\oplus a_y\)

现在问题变成了做两次:求根到某个节点的路径上的所有点的 \(ans\)

发现这个“子树外”的范围随着 dfs 过程是在不断增加的,所以依旧利用 01trie 即可。

时间复杂度 \(O(n\log w)\)

记录

6. Path Counting

考虑设 \(f(u,d)\) 表示深度为 \(u\) 的点有多少个深度为 \(d\) 的儿子,\(g(u,d)\) 表示以 \(u\) 为 LCA 的路径有多少条长度为 \(d\) 的,则 \(f\) 容易 \(O(n^2)\) 计算,\(g\) 首先算上 \(f\),然后再做一个卷积。这样得到一个 \(O(n^3)\) 的做法。

发现 \(f(u,d)\) 的生成方式很有特色:\(\prod_{i=u}^{u+d-1}a_i\),实际上就是 \(\frac{pre_{u+d-1}}{pre_{u-1}}\)

\(g(u,d)=\dbinom{a_u}{2}\times \sum_{x+y=d-2}f(u+1,x)\times f(u+1,y)\)

我们把组合数去掉的结果重新记作 \(g\)

考虑在 \(O(n^2)\) 的时间内计算出这 \(n^2\) 个卷积的结果,显然我们只考虑 \(u\) 相同的 \(O(n)\) 个点值没办法相互转移,这个和传说中的组合数下指标求和的一个套路形似,就是在 \(u-1\)\(u\) 之间转移,因为我们会发现 \(g(u,d)\) 里的任何一项 \(f(u+1,x)\times f(u+1,y)\) 都可以对应到 \(f(u,x)\)\(f(u,y)\) 上,也就是 \(g(u,d)\)\(g(u-1,d+2)\) 存在对应关系,也就是有 \(g(u,d)=\frac{1}{a_{u}^2}g(u-1,d+2)\),但这并不完全对,因为我们证明了 \(g(u,d)\) 的每个元素可以对应到 \(g(u-1,d+2)\) 中,但是 \(g(u-1,d+2)\) 的计算中,当且仅当 \(x=0 \or y=0\) 的时候,我们无法将其对应到 \(g(u,d)\) 上,所以先减去这部分(如果存在)。

因此我们只需要暴力卷出所有的 \(g(1)\) 即可,时间复杂度 \(O(n^2)\)

记录

7. Many Easy Problems

自然的考虑对于每个点,计算多少个子集经过它。

然后考虑计算多少个子集没有经过它。所以初始所有的 \(ans_k\) 都是 \(n\times \dbinom{n}{k}\),然后我们枚举点 \(u\),枚举 \(k\),进行去重。

那么没有经过的话,就是以 \(u\) 为根分出的某个子树落满了 \(k\) 个点。

也就是 \(\sum_{i}\dbinom{sz_i}{k}\)

我们发现这个和 \(u\) 到底是哪个点没任何关系。最开始枚举 \(u\),然后枚举到一个 \(sz_i\),就把 \(cnt_{sz_i}+1\),最后我们计算的就是:

\[ans_k -= \sum_{i}cnt_i\dbinom{i}{k} \]

这是标准差卷积形式。

时间复杂度 \(O(n\log n)\)

记录

8. Donation

难得能独立想出 ARC 的最后一题啊。

考虑把过程倒过来,也就是说我们初始在一个位置 \(u\) 且拥有 \(x\) 的钱,然后当你第一次踩到 \(u\)(包括起始位置)的时候获得 \(b_u\) 的钱,显然如果你想踩到 \(u\) 则你至少需要拥有 \(c_i=\max\{a_i-b_i,0\}\) 这么多钱。我们可以任意决定初始的 \(u\)\(x\),只需要保证 \(x\ge c_u\) 即可,同时我们想让在能遍历所有点的情况下,这个 \(x\) 尽可能地小。

图的限制是不好做的,我们考虑转成树,一个想法是建立 MST,但是我们的边是无权的而点有权,考虑把点权转成边权,我们会发现相当于给每条边 \((u,v)\)\(\max\{c_u,c_v\}\) 的边权,我们证明之:

不妨设 \(c_u\ge c_v\),则如果你想从 \(v\) 走到 \(u\),显然要大于等于 \(c_u\);否则你已经踩在了 \(u\) 然后要到 \(v\),也就是说你的钱已经大于等于 \(c_u\) 了,此时把边权设成 \(c_u\) 显然不影响。

现在我们的图被简化成了一棵树,我们发现这个过程非常自然地和 Kruskal 重构树对应,所以我们更进一步建出重构树,则任意时刻你能走到的点都是属于一颗子树的。

我们此时观察我们的过程:相当于你是从一个叶子 \(u\) 出发,不断进行:从 \(u\) 跳到 \(fa\),钱数加上 \(subtree(fa)\)(挖掉 \(subtree(u)\))内的所有点的 \(b\),直到跳到 \(1\),中间过程中你要保证你从 \(u\) 跳到 \(fa\) 的时候钱不少于 \(c_{fa}\)(我们定义方点的 \(c\) 是它代表的那条边的边权,然后我们不再区分方圆点,容易发现随着你不断向下 \(\text{dfs}\) \(c\) 是越来越小的。),最后要能跳到 \(root\)(代表我们能遍历到所有点),且要求到根的时候拥有的钱最少。

\(f(u)\) 是从 \(u\) 子树内某叶子跳到 \(u\) 并且结尾拥有的最少钱数,设 \(sz_u\)\(subtree(u)\) 内所有叶子的 \(b\) 的和,则有:

\[f(u)= \begin{cases} \max\{a_u,b_u\} (\text{u is a leaf}) \\ sz_u+\min\{f(v)+\max\{0,c_u-f(v)\}-sz_v \mid v\in son_u\} (\text{u is not a leaf}) \end{cases} \]

时间复杂度 \(O(m\log m)\),瓶颈在于排序。

记录

9. Google Code Jam

考虑若确定了做哪些题,怎么安排顺序让期望罚时最小。

我们先忽略 Large Task 的前置约束,然后使用 exchange argument 得,我们比较的就是 \(\frac{timeLarge\times (1-p)}{p}\) 的大小(这里的 \(p\) 是成功率,和题面中有别)。

容易发现按照这个值排序,总能保证所有的 Small Task 都在 Large Task 前面,因为 Small Task 的 \(p=1\)

所以我们排序后按照这个顺序做 dp。

考虑设 \(dp(i,j)\) 是考虑完了前 \(i\) 道题,使用的 Small Task 和 Large Task 拢共使用了 \(j\) 的时间,能得到的最大期望收益,以及在此基础上的最小期望罚时。

如果我们做了 Small Task,相当于将所有的 Large Task 向后平移了 timeSmall 位,所以罚时直接加上 \(timeSmall\)

在此基础上,如果我们还做了当前的这个 Large Task,则这个,最后一个 Large Task 的结束时间是已知的,而对于前面的所有 Large Task,由它贡献罚时的概率应该乘上 \((1-p)\)

这样我们就在 \(O(nT)\) 的时间复杂度内做完了这个 dp。有一说一我觉得本题精度应该做不到 \(10^{-9}\) 但反正你假装做到了,开 long double 就能过了。

记录

10. Long Distance Coach

很妙的题啊。

首先,如果我们把所有人按照 \(D\) 排序,则每一段路程(相邻两个接水处,我们认为开头和结尾也算)下车的人一定是一段连续的区间,且如果非空,最后一个接水的人一定会下车,也就是说若干个区间,它们的右端点都属于一个确定的集合 \(S\),这个 \(S\) 就是每一段路程最后一个接水的人,设为 \(p_i\)(以下司机都不算人谔谔)构成的集合。

但是我们仍然无法高效地描述,我们到达某个站点时,剩余人的情况。换言之按时间顺序 dp 的想法行不通。

这题比较妙的就是这个 dp 的形式:我们从每个人的角度入手,如果一个人最后活着,那么他的贡献是确定的 \(W\times \left\lfloor \frac{X}{T} \right\rfloor\);如果一个人下车了,就比较复杂。

我们不妨假设我们知道了哪些人是会下车的,我们思考一下如何决定他们何时下车。显然,一个人能下的时候就要尽快下车(也就是说,如果一个人 \(x\) 在时刻 \(i\) 下车,显然有 \(x\le p_i\),且 \((x,p_i]\) 这一段都是要下车的)。

这个下车的条件实质上有些难以处理,因为我们要顾及到后面的人能不能下的问题。所以我们换个思路:我们保证一个 \(x\in S\) 是要下车的,那么它那次下车,会让一段连续区间 \([y,x]\) 的人都下车(P.S. 如果我们每次的区间都是 \([1,p_i]\) 那么每次让一段区间的人下车显然是对的,如果是 \([s_{i-1},p_i]\) 也一样,因为如果 \([y,p_i]\) 溢出了 \(s_{i-1}\),那么这部分归属于上一个区间即可,会更优秀)。

因此设 \(f_i\) 是前 \(i\) 个人的最优解法,我们设 \(t_i\) 是最小的 \(s_x\) 使得 \(p_x=i\)(没有则为 \(\infty\)),那么,如果我们不扔掉第 \(i\) 个人,就是 \(f(i-1)+W\times \left\lfloor \frac{X}{T} \right\rfloor\),否则如果我们删掉 \((j,i]\) 这一段,那么就是 \(f(j)+\sum_{k=j+1}^{i}c_k+W\times (i-j)\times \left\lfloor \frac{t_i}{T} \right\rfloor\)

\(t_i\) 可以把所有的 \(\{s_i\bmod T,s_i\}\) 排序,然后单调队列算出,复杂度 \(O((n+m)\log)\),瓶颈在排序。

然后正式 dp 的过程显然是 \(m^2\) 的。

优化也很简单,就是一个斜率优化的形式,这里询问的斜率是 \(p_i\),不单调,所以在下凸壳上二分即可。

时间复杂度 \(O((n+m)\log)\)

记录

11. Bitwise Xor

感觉这场的题都很有水平啊。

我们考虑建 trie,然后考虑最高位:如果为 \(0\),则问题变成了在 \(0/1\) 两个子树里面选点的子问题,因为你从左右各拿出一个它们的 xor 一定合法。

如果为 \(1\),则我们要么只选择一个点;同时不可能选择三个点;如果选择了两个点,必定是一个在左边一个在右边。

我们暴力 dfs 找到左子树里存储的所有数,暴力枚举这个数 \(u\),现在问题变成了刚才我们所找到的那颗右子树里多少个点 \(xor u\ge lim\),这个可以简单地在 trie 上 \(O(\log w)\) 地完成。

时空复杂度均为 \(O(n\log w)\)

记录

12. Grammarly

首先,有一个 \(n^2\) 的 dp,就是说如果 \(s(i,j-1)=s(i+1,j)\) 那么 \(dp(i,j)=1+dp(i,j-1)\),否则 \(dp(i,j)=1+dp(i,j-1)+dp(i+1,j)\),最后 \(dp(1,n)\) 就是答案。

\(s(i,j-1)=s(i+1,j) \Leftrightarrow s(i\sim j)\) 全部是一个字符。

如果忽略这个 special case 则容易发现答案就是 \(2^{n}-1\),也就是说,我们枚举一个子串(一个子串可能会被枚举多次),设出现在 \([L,R]\),则其造成 \(\dbinom{n-(R-L+1)}{L-1}\) 的贡献,也就是从 \([1,n]\) 开始,每次要么弹出左边要么弹出右边。

问题在于如果你当前的串是同一个字符组成的,那么我们弹左边和弹右边要被视作一种操作。

把所有同色极长段拉出,我们分别对每个段 \([L,R]\) 来考虑,因为根据上面的描述,我们容易发现一个区间的计算有问题,必须满足它是一个极长同色段的子段。

我们分为两部分:去掉这些段的错误贡献;加上新的贡献。

去掉贡献的话,我们枚举 \(len\in [1,R-L+1]\),然后考虑去掉所有 \([i,i+len-1]\) 的贡献(因为这些段的组合数上标都是确定的 \(n-len\)),我们发现此时的贡献和是一段下指标求和:\(\dbinom{n-len}{L-1}\sim \dbinom{n-len}{R-len}\),我们可以把组合数的 \((n-len)!\) 提出来,然后变成了一个 \(\frac{1}{n!}\) 序列的卷积,且两边序列的项数都是 \(O(l)\) 级别的(\(l=R-L+1\)),可以直接 NTT。

加上新的贡献则是容易的,我们设串在长度为 \(len \in [1,l]\) 的时候第一次变成了全是这个字符的串,则最后的结尾形态有 \(len\) 种可能(也就是 \(1\) 个字符,\(2\) 个字符,..,\(len\) 个字符),我们枚举这一次删除的是左边的还是右边的字符,后面的操作方案全都是一个相同的组合数。

时间复杂度在于第一部分,\(O(n\log n)\)

记录

13. Interactive Vertex

考虑一下树是菊花图怎么做,然后我们发现是可以在 \(O(\log n)\) 的次数内问出来的。

把菊花图的想法拓展一下会发现我们实质上可以做这样一个东西:就是随便找一个点定根,然后可以在 \(O(\log deg)\) 的时间内问出来到底在根的哪颗子树内。

如果直接套用点分治的话就可以有一个上限 \(O(\log^2 n)\) 的做法了。但我卡了三四发也卡不进去。

然后我们发现我们先找重心,再二分找到一颗确切子树,其实不如这样:每次排除一半的子树后,对连通块重新寻找重心,来的更优秀。

这样询问次数就进入玄学模式了,不过我们至少能看出比直接点分要不劣。

交上去 wa on 35,然后我们把二分选择的那一半子树加个random shuffle(也就是你随机的选出一半子树)就过了......

不会分析次数啊。

记录

14. Alchemy

题目意思即为:

\[f_n(x)=(1+x)^A\times \prod_{i=2}^{n}(g_ix+1) \\ g_n=[x^n]f_{n-1}(x) \]

\(g_N\)

可以认为 \((1+x)^A\) 的 degree 是 \(O(N)\) 级别的,因为我们关注的项不超过 \(x^N\)

考虑分治 NTT,容易发现递归到一个长度为 \(L\) 的区间时,我们只关注 \(2\times L\) 项的前置系数啊,这也是 \(O(L)\) 的。

所以有 \(T(n)=2T(n/2)+O(n\log n)=O(n\log^2 n)\)

问题变为计算 \(f_1(x)\) 的前 \(O(n)\) 项系数,最暴力的想法是跑多项式快速幂,这样的话,这部分用时甚至要比后面还慢;一个正确的想法是把 \(\dbinom{n}{i}\) 看作 \(\frac{x^{\underline{i}}}{i!}\),然后我们可以 \(O(n)\) 计算出 \(\dbinom{A}{0}\sim \dbinom{A}{n}\)

时间复杂度 \(O(n\log^2 n)\)

记录(暴力多项式快速幂做的所以很慢)。

15. Fast Spanning Tree

很厉害的题。

考虑如果 \(S_a+S_b \le x\),我们设 \(r=\left\lceil \frac{x-S_a-S_b}{2} \right\rceil\),则至少有一边需要增加 \(r\),才会合法。

所以我们当且仅当有一边增加了 \(r\) 时,才会重新检查这条限制的合法性;如果不合法,我们继续利用相同的手法,容易发现每条限制检查的次数不会超过 \(\log w\) 次。

现在我们来考虑实现:我们注意到我们判断的是“增加量”是否大于等于 \(r\),所以我们应该把 \(S_a+r\)\(S_b+r\) 分别压入两个连通块中,当我们看到 \(sum\ge tag\) 的时候,说明 \(tag\) 所表示的这个约束,至少有一边合法了,此时我们把这条约束拿出来重新判断。

具体而言我们维护一个 \(S\),表示当前状态下,不经过任何额外合并,就可以完成的操作集合,这个可以通过我们在输入的时候检查一遍来初始化。我们每次取出 \(S\) 中最小的元素,然后考虑合并两颗子树(当然,有时候是会出现两棵子树已经合并在一起的情况),我们考虑启发式合并:把 \(tag\) 数目比较少的合并到比较多的一颗树上。那么我们每次取出 tag,如果在合并子树后已经满足了条件,就先 check 一遍;否则我们直接把这条约束压入另一棵树。然后我们重新在另一棵树的小根堆中不断检查即可。

一个比较松的上界是,把 \(n\log w\)\(tag\) 全部利用 pq 启发式合并起来的复杂度,显然是 \(n\log^3\) 级别的。当然这个显然跑不满;更优秀的复杂度我不太会分析。

记录

16. Good Pairs

感觉严格比 E 简单,所以放在了前面。

不妨设 \(a_l\le a_r\),那么我们考虑一个贪心,就是如果当前的这个位置它比上一个位置大(严格大于),但是差不超过 \(k\),且比 \(a_r\) 小,就跳到这个位置。

如果没有 \(a_r\) 的限制显然每个点会往后跳的位置是唯一的,我们记作 \(R\)(当然也有时候找不到)。

则贪心过程本质上是从 \(i\) 出发沿着 \(R\) 跳,然后跳到一个 \(j\),发现跳到 \(R_j\) 后就不合法了(要么大于了 \(a_r\) 要么到了 \(a_r\) 后面)此时一步跳到 \(a_r\)

考虑枚举这个“最后一个跳到的位置”,然后我们发现我们并不关注起跳点 \(a_l\) 是什么,只关注多少个起跳点能跳到枚举的位置 \(x\),这可以简单地 \(O(n)\) 计算。然后我们就是考虑多少个位置,可以且必须一步跳到,显然就是后缀 \([x,n]\) 这里面,值在 \([a_x,a_x+k)\) 的数的数目。

此时我们就变成了一个 DS 问题,第一眼上主席树,第二眼是离线的,我们倒着维护 bit 就行了。

对于 \(a_l\ge a_r\) 同理,最后对 \(a_l=a_r\) 去重即可,时间复杂度是 \(O(n\log n)\),常数不大。

记录

17. Tree Sum

感觉是质量很高的数数题。

感觉这个东西有点复杂所以想一下有多少颗合法的树,然后发现这个好像还真的不会做...

考虑树的形态确定了,有多少种填法,怎么这个还是不会?

冷静想一下发现所有叶子到父亲的边都是 \(-1\),然后我们把叶子都删了,会新形成一些叶子,它们会根据子树内的信息决定它到父亲的边到底是 \(1\) 还是 \(-1\)

这样的话填法就可以唯一确定,但我们想一下如果到根的时候它的儿子有偶数个选了 \(-1\),那这就不合法了,换言之我们只能说明填法 \(\le 1\) 种。

这下给我整不会了,冷静一下我们想一下菊花图怎么办,我们会发现菊花图的话,如果是奇数那么一定不合法,偶数就一定合法。

能不能把这个结论推广,想一下是可以的,因为一个大小是偶数的树,必定有奇数颗大小是奇数的子树,那么所有大小是奇数的子树由于不合法(由归纳得)所以它们到父亲的边必须是 \(-1\),其余必须是 \(1\),还真是对的...

所以如果 \(n\) 奇数无解,否则确定了树就有一种唯一的填法。

现在考虑原问题就有眉目了,因为你不用关注到底怎么填边权进去了......

\(\sum\sum\) 这种二重和式,常见套路是交换求和顺序(在这种隐式地求和时,我们也会表述为考虑每条边的贡献),也就是我们枚举一条边 \((u,v)\),并且钦定 \(fa_v=u\)\(n\in subtree(v)\)\(1\) 永远是根节点,考虑 \((u,v)\) 这条边,由刚才结论得如果 \(v\) 子树是奇数赋 \(-1\) 否则赋 \(1\)

我们可以暴力枚举 \(subtree(v)\) 这样就有了 \(O(n^3)\) 做法,但是绝大多数的 \((u,v)\) 是无区别的,只有四类:

  • \(u,v\in [2,n-1]\)

  • \(u=1,v\in [2,n-1]\)

  • \(u\in [2,n-1],v=n\)

  • \(u=1,v=n\)

然后就可以在 \(O(n\log p)\) 的时间内解决这个问题,瓶颈在于对于每个 \(i\in [2,n]\) 计算 \(i^{i-2}\)

记录

18. Buying Sets

如果建立一个二分图,左部是集合,右部是数,然后集合向集合里的数连边,根据给出的约束,由 Hall 定理得原图一定存在完美匹配。

虽然我们没看出有什么用,但我们可以先求一组匹配出来。

然后我们发现如果我们选择一个集合 \(S\),对于所有集合 \(S\) 里的元素 \(u\),和 \(u\) 匹配的点都要被选。

至此转成了最小权闭合子图,取相反数后跑一次最大流即可。

记录

19. Magician and Pigs (Hard Version)

挺好的题,赛场上还是脑子太乱了,都没意识到复杂度是错的。

按照 repeat 把 create 和 damage 分段,也就是形如 \(AxBxCxD\) 这样的(x 是 repeat)。

把这个展开会得到 \((AxBxC) + (AxBxC) + D \rightarrow AxB+AxB+C+AxB+AxB+C+D=AAB AAB C AAB AAB C D\)

熟悉了展开过程你会发现如果一个位置后面有 \(k\) 次 repeat 那么它会一共出现 \(2^k\) 次。

所以我们会猜测有意义的 repeat 是 \(30\) 次这样的一个方向。

考虑第 \(a\) 段的一个操作,如果 \([1,a]\) 这些段有一次 damage 操作那么第 \(a\) 段的一个 create ,至多是最后的 \(10^9\) 次会有贡献。

我们此时可以考虑二分最后一次有贡献的位置。设为 \(k\),问题变成了判断合法性。

考虑这个展开结构就是一个 \(L\) 层的二叉树(\(L\) 是段数),所以我们可以 \(O(L)\) 地在这棵树上递归,但是 \(L\) 的上界是 \(O(n)\) 级别的。

如果我们在 \(L\) 层,然后我们枚举的那个 create 是在第 \(x\) 段的,那么如果你递归到了左子树,右边会多出 \(2^{L-x}\) 个同类型的 create。也就是说除非 \(L\le x+30\),否则你一定是不断走右子树的,所以我们单次 check 的复杂度可以进一步优化到 \(O(\log)\),这样这一部分就是 \(O(n\log^2)\) 的。

\(pos\) 是第一个有 damage 的段,则 \(pos\sim L\) 这些段都可以用上面的做法;然后我们知道 \(1\sim pos-1\) 都没有任何 damage 存在;考虑所有的第 \(pos\) 段,它们会把我们枚举的 create 分成若干部分,设 create 在第 \(x\) 段则每一部分都恰好有 \(2^{pos-x}\) 个 create。显然只有最后不超过 \(10^9\) 级别的部分是有意义的,我们用相同的手法二分即可。

时间复杂度 \(O(n\log^2)\)

显然这个做法是可以支持 \(O(\log^2)\) 单点修改一个 create 的值,然后重新查询的!

记录

20. 珍珠

感觉这个题不是很难啊,谔谔。

\(f(i)\) 是钦定了 \(i\) 个颜色出现了奇数次的方案数

\(g(i)\) 是恰好 \(i\) 个颜色出现了奇数次的方案数,则有:

\[f(i)=\sum_{j\ge i}\dbinom{j}{i}g(j) \]

因此:

\[g(i)=\sum_{j\ge i}(-1)^{j-i}\dbinom{j}{i}f(j) \]

如果计算出了 \(f(i)\),就可以在 \(O(D\log D)\) 的时间内反演出 \(f\),现在问题变为计算 \(f\)

钦定 \(i\) 个颜色的方案有 \(\dbinom{D}{i}\) 种,然后考虑 \(\text{EGF}\) 卷积,设出现奇数次的 \(\text{EGF}\)\(F(x)\),不做限制的 \(\text{EGF}\)\(G(x)\),则有:

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

我们要求的是 \([\frac{x^n}{n!}]F^i(x)G^{D-i}(x)\)

也就是:

\[(\frac{e^x-e^{-x}}{2})^ie^{x(D-i)} \\ (\frac{1}{2^i})(e^x-e^{-x})^ie^{x(D-i)} \]

把中间部分二项式定理展开:

\[\sum_{j\le i}e^{jx}\times (-1)^{i-j}\times e^{-x(i-j)}\times \dbinom{i}{j} \\ \sum_{j\le i}(-1)^{i-j}\dbinom{i}{j}e^{x(2j-i)} \]

然后把后面的 \(e^{x(D-i)}\) 乘进去:

\[\frac{1}{2^i}\sum_{j\le i}(-1)^{i-j}\dbinom{i}{j}e^{x(D+2(j-i))} \]

此时可以 \(O(D^2)\) 计算 \(f(0\sim D)\) 了。

显然这是一个卷积的形式,因此可以 \(O(D\log D)\) 的时间内计算出 \(f(0\sim D)\)

记录

21. 氪金手游

题目要求对每种生成的 \(W\),求生成概率 $\times $ 此时抽卡的合法概率之和。所以我们考虑如果随机权重 \(W\) 已经确定,如何计算合法的抽卡概率。

题目里的 \(n-1\) 很容易让人联想到树;事实上如果把边看作无向边确实是一个树形结构(那个形式化限制保证了看成无向图的时候,图是联通的)。但是它既不是内向的;也不是外向的。

如果这棵树是外向的,那么对于一个 \(u\),第一次抽到 \(u\) 要在所有 \(u\) 子树内的点之前。

设整体的权重和为 \(S\),子树内的权重和为 \(T\)(包括点 \(u\) 的权重),点 \(u\) 的权重是 \(a\),则设 \(p\) 为随机到一个 \(u\) 子树外的点的概率,\(q\) 是随机到点 \(u\) 的概率,就有:

\[p=\frac{S-T}{S},q=\frac{a}{S} \]

而让点 \(u\) 在子树内最早出现的概率是:

\[q+pq+p^2q+...=q(1+p+p^2+...)=\frac{q}{1-p}=\frac{a}{T} \]

所以我们实质上只关注子树内的随机权和。

\(W\) 确定的时候,我们 DFS 一遍树就能求得答案。

\(W\) 不确定的时候,容易想到设 \(f(u,x)\) 表示 \(\sum_{S}P(S)\times G(S)\)\(P(S)\) 是子树内生成 \(S\) 这个局面的概率;\(G(S)\) 是在局面 \(S\) 下抽卡使得子树 \(u\) 合法的概率;而 \(S\) 是满足随机权重和 \(=x\) 的局面。这样直接背包就可以 \(O(n^2)\) 求得答案。

考虑现在,有一些边的方向是反的。我们采用容斥:设 \(E\) 是所有反边的集合,钦定 \(E\) 的一个子集 \(T\) 内的边全部是正向,剩下的边我们不管,显然容斥系数是 \((-1)^{|T|}\)

则我们发现现在构成了若干森林;所以当遇到反边的时候,你要么把他视为不存在(但是注意每个状态要乘上子树 \(v\) 合法的概率);要么视为一条正边且在转移的时候乘上 \((-1)\) 即可。

时间复杂度 \(O(n^2)\)

记录

22. Snowy Mountain

经过一些归纳整理,我们的行走路径一定是 \(u\rightarrow v\) 的最短路径,其中最多在一个点 \(w\) 的时候,会反复来回在 \(w\) 和它的一个同高度邻居间横跳,最后回到 \(w\),一口气走到 \(v\)。且满足 \(w\rightarrow v\) 这一段的高度是不断严格下降的。

\(f(u)\) 是从 \(u\) 出发,不断严格下降高度,所能走的最大步数;那么上面的路径,可以看成 \(u\rightarrow w\),然后反复横跳回到 \(w\),然后加上 \(f(w)\)。这样我们就可以用简单路径的形式描述我们的行走,把所有简单路径以外的部分用一个简单的贡献形式来描述。

我们把路径上,势能增加的边给上 \(+1\) 的权,势能减少的边给上 \(-1\) 的权(当然有一些边禁止通行)。那么合法的充要条件是最小前缀和非负,设最后总共的和是 \(d\)(也就是走到 \(w\) 后余下的势能),如果我们要进行反复横跳,那么我们应该是可以走 \(\lfloor \frac{d}{2} \rfloor\times 2\) 也就是 \(d-[2\nmid d]\) 这么多步。

首先考虑点分。这样我们可以对每个点 \(u\),处理 \(u\) 上行到 \(rt\) 以及从 \(rt\) 下行到 \(u\) 的信息。我们考虑拼接两部分,那么只需要分别维护两端的 \((premin,endv)\),分别表示最小前缀和以及最后总共的和。

然后设上行段是 \(L\),下行段是 \(R\),那么最小前缀和非负的话,也就是:

\[\begin{cases} premin_L\ge 0 \\ endv_L+premin_R\ge 0 \end{cases} \]

看上去是一个二维数点的形式。实际上如果 \(premin_L\lt 0\) 我们直接忽略这个点,这样就只剩下一个维度的限制了,可以直接 bit 上解决。(点分治为了解决相同子树问题,要正着反着遍历一遍,这个过程决定了它是一个“在线”的数点,因此这个一维数点也必须用 BIT 维护前缀 \(\max\))。

贡献可以拆成 \(depth_u+depth_v+f(v)\),然后我们还要分类:也就是到底是否进行反复横跳(因为不是所有的点 \(w\) 都可以反复横跳的)。

如果不能横跳,那么直接 \(depth_u+depth_v+f(v)\) 完事(事实上 \(depth_u+depth_v\) 也是可以的)。

如果可以横跳,那么我们发现 \(d=endv_L+endv_R\),暴力枚举两个 \(endv\) 的奇偶性就可以确定 \(d\) 的奇偶性。所以我们加入一个点的时候要加入到其 \(endv\) 所属奇偶性的 bit(还要根据是否能成为反复横跳点分类,所以实质上有 \(4\) 个 bit)。然后查询 bit 的时候再去暴力枚举 \(4\) 种 case,此时的贡献是容易统计的。

时间复杂度确实是 \(O(n\log^2 n)\) 但是常数也确实很大。

记录

23. Paper Task

看到本质不同串计数上来拍一个 SAM 先;然后我们考虑对每个节点都是若干长度连续的,且右对齐的串。

括号串合法的判定是从左往右的,最小前缀和非负且总和为 \(0\);我们先把串反转,那么变成了最小后缀和非负且总和为 \(0\);最小后缀和非负可以二分 + ST表得到一段区间;总和为 \(0\) 可以用 vector + 二分,总复杂度都是 \(O(n\log n)\) 的。

记录

24. Mr.Aoki Incubator

首先,一个人如果染色了,则所有它能追上的点,以及能追上它的点都可以看作被染色了。

也就是说如果以他为原点建立 \(x-v\) 坐标系则第二第四象限的点都等于被染色了。

但仔细考虑后发现还有一种可能:如果三个点 \(a,b,c\) 的初始位置依次递增且 \(b\) 染色,然后 \(b\) 先超过 \(c\) 并且对他染色;然后 \(a\) 后来超过 \(c\) 被染色。

换言之如果一个染色人能追上一个速度为 \(v\) 的点,则他前面所有速度大于 \(v\) 的点都能被染色(而不仅仅是大于染色人速度的那些点)。

对称的结论是,如果一个染色人能被速度为 \(v\) 的点追上,则他后面所有速度小于 \(v\) 的点都能被染色。

此时重新审视二维平面上的结构,我们发现一个人实质上会影响纵向(按照 \(v\) 排序)的一段区间的点!

因此按照 \(v\) 排序后根据上面的分析可以求出 \(n\) 个区间,问题变成了选若干个,它们的并是 \([1,n]\) 的方案数,这是经典问题,将区间按照 \(r\) 升序排序后可以 dp+seg 解决。时间复杂度 \(O(n\log n)\)

记录

25. Unique XOR Path

考虑一个 bit 可以把给出的路径 \(S\) 和其它的一些路径区分开来。目的是对于任何一条 \(V\neq S\),至少有一个 bit 把 \(S,V\) 区分了。

设转折点有 \(a\) 个,一个容易的观察是:\(k\ge a\) 是一定有解,理由如下:

我们考虑 \(S\)\(V\) 第一次出现不同的位置,我们可以根据转折点划分出 \(a\) 段(最后一段不可能出现不同,因此不是 \(a+1\) 段),我们每次在一段的首尾两个转折点放上一个 \(1\),其余位置都是 \(0\),就可以区分出所有在这一段第一次出现不同的位置。

这个理由看上去很像必要的。仔细手玩一下:发现有一种 corner case,我们其实可以一次区分出 \(len+1\) 种不同的位置而不是 \(len\) 种(在首尾放一个 bit 以外,在尾转折点的下一个位置(如果路径此时往右,那么往下放一个bit;否则往右放一个 bit),这样,在两个转折点相邻的时候就可以节约一个 bit 出来。

时间复杂度 \(O(n+m)\)

记录

26. Large Heap

\(LCA(u,v)=1\),我们事实上只关注两条链:\(1\rightarrow u\)\(1\rightarrow v\),初始时候 \(1\) 节点的值就一定是 \(1\),我们把两条链的 \(1\) 去掉。

对逆排列计数:也就是设 \(pos_i\)\(i\) 在哪个节点,然后按照 \(pos_2,pos_3,pos_4,....,\) 的顺序加点,我们称这个过程为“点亮”。

则任意时刻两条链分别都有一段前缀被点亮。题目要求的就是算 \(u\) 这条链先被点亮的概率。

\(dp(i,j)\) 表示第一条链被点亮了前 \(i\) 个;第二条链前 \(j\) 个的概率;考虑转移,我们可以只关注两条链的下一个子树,其它的点不关心,所以可以假设不关心的点都被点亮的。

现在问题变成有 \(sz_1+sz_2\) 个数没有分配,有两颗树,大小分别为 \(sz_1\)\(sz_2\),如果等概率随机分配,则最小的数分配到两棵树的概率分别是多少。

显然分别是 \(\frac{sz_1}{sz_1+sz_2},\frac{sz_2}{sz_1+sz_2}\),因此转移得到了解决。时间复杂度 \(O(n^2\log n)\)

记录

27. Arkady and Rectangles

扫描线,然后我们方便起见,先假设没有两个时间在同一时刻发生。

如果我们加入一个颜色 \(col\),显然除了颜色 \(col\) 不会有颜色从不合法变为合法;但删除的时候可能会有,且不止一个颜色这样。

所以无法在一次操作后就立刻能快速维护出所有从不合法变为合法的颜色。

但我们可以维护最大的,从不合法变为合法的颜色。然后去掉这个颜色后重新维护也是可行的。

具体实现的话,每个节点维护两个 set:\(p\) 表示挂在这个节点的颜色集合;\(rest\) 表示挂在这个节点的不合法颜色集合。再维护 \(mn\) 表示其代表的 \([l,r]\) 内最小的可见颜色;$mx $ 表示子树内能向上走到当且节点的最大的不合法颜色(向上走是这样一个过程:如果一个节点 \(u\) 挂了一个颜色 \(col\),首先 \(col\) 出发的时候满足 \(col=mn_u\),然后对于所有祖先 \(a\),有 \(col\ge \max\{p_u\}\),这样 \(col\) 才是可见的,我们维护的就是这个过程)。

然后发现这个东西完全可以处理同一时刻多个事件的 case,没什么特判的。

时间复杂度 \(O(n\log^2 n)\)

记录

28. Same Descent Set

可以研究一整天的数数,给佳和sjc场切磕头。

接下来我们称 \(a_i\)\(P_i\)\(P_{i+1}\) 的大小关系,对于 \(Q\) 类似地定义 \(b_i\)

考虑容斥。一个错误的思路是(这个不重要,只是我自己第一个得到的错误想法):枚举第一个 \(a,b\) 不同的位置 \(x\),那么前半部分的方案数是 \(f(x)\),后面随便排;问题在于你不能保证 \(a_x\neq b_x\),如果这里再套一个容斥(就是说,去掉 \(f(x+1)\)),那么最后会看到一个叠进和的形式 \(\sum a_if(i)-b_if(i+1)\),然后会发现 \(a_{i+1}=b_i\) 最后会把除了 \(f(0)\) 的项都消去;最后会得到一个没有任何未知数的恒等式......

然后考虑一下看上去很暴力的想法:我们钦定 \(S\) 集合,是 \(P,Q\) 都取小于号的位置,我们现在要求计数这样的排列有序对数:首先 \(a,b\) 对应项相等;然后 \(S\) 中的位置取小于号,\(S\) 以外的位置取大于号。

\(U=\{1,2,...,n-1\}\),我们考虑此时相当于有 \(2|S|\) 个条件,前 \(|S|\) 个是说对于 \(i\in S\),有 \(P_i\lt P_{i+1}\),后 \(|S|\) 个是说对于 \(i\in S\),有 \(Q_i\lt Q_{i+1}\),把条件集合记作 \(X\)

\(2|S|\) 个条件进行容斥,也就是说我们枚举 \(V\subset X\),容斥系数是 \((-1)^{|V|}\),我们把“条件集合” \(V\) 中的内容分成两部分 \(V_p,V_q\),分别对应了对 \(P\) 排列的约束和对 \(Q\) 排列的约束。那么我们现在要计数:

  • \(P\)\(U-S\) 的位置都填小于号,且 \(V_p\) 代表的位置也填小于号;剩余位置不管,这样的 \(P\) 数目。

  • \(Q\)\(U-S\) 的位置都填小于号,且 \(V_q\) 代表的位置也填小于号;剩余位置不管,这样的 \(Q\) 数目。

我们发现 \(P,Q\) 并无本质不同,因此我们定义 \(f(V)\) 是满足下列条件的排列 \(p\) 的数目:

\(p\)\(U-S\) 的位置都填小于号,且 \(V\) 代表的位置也是小于号;剩余位置不管,这样的 \(p\) 的数目。

则我们要累加上的也就是 \((-1)^{|V_p|+|V_q|}f(V_p)f(V_q)\),重新定义 \(f(V):=(-1)^{|V|}f(V)\),则我们最后要求的是:

\[\sum_{S\subset U}\sum_{V_p\subset S}\sum_{V_q\subset S}f(V_p)f(V_q) \]

现在我们考虑交换求和顺序,但如果前面的推导中我们足够细心,就会发现一个致命的问题:\(f(V)\) 的计算是依赖 \(S\) 的:仔细去看定义,强制填小于号的有两部分,一部分是 \(V\);另一部分是 \(U-S\)

现在,我们改变枚举的内容的对象,改为枚举 \(S,V\) 的差,也就是:

\[\sum_{S\subset U}\sum_{V_p\subset S}\sum_{V_q\subset S}f(S-V_p)f(S-V_q) \]

现在我们进行替换,令 \(f(V):=f(S-V)\)(细心的话,可能会注意到容斥系数的指标也该变化,但我们发现 \((-1)^{2|S|-|V_p|-|V_q|}=(-1)^{|V_p|-|V_q|}\)),那么我们式子的形式没有变,但是由于 \(f(V)\) 的意义变为了,除了 \(V\) 集合以外的位置强制填小于号,合法的排列数目乘上容斥系数;所以 \(f(V)\) 并不依赖于 \(S\) 究竟是多少,所以现在我们可以计算:

\[\sum_{V_p}\sum_{V_q}\sum_{V_p,V_q\subset S}f(V_p)f(V_q) \]

在进一步地探讨之前,我在想能否把这个推导容斥的过程更简单化,毕竟官方题解就寥寥数语而我转化了半天。

我们先考虑类比二项式反演,推出一些我们想要的意义。我们并不能真的完全看作二项式反演,毕竟你从 \(2|S|\) 个条件里任意选出 \(k\) 个得到的并不是一样的东西,但我们可以用这种方式去确定我们要求的是“至多”还是“至少”,还是一些别的什么,就是说确定我们到底要容斥什么,这在有时候脑子宕机的时候可能是一个手段。

这里大概是要通过求 \(g\) 反演出 \(f(2|S|)\) 这样一个东西,那么二项式反演有两种,一种是 \(f(n)=\sum_{i\ge n}\) 一种是 \(f(n)=\sum_{i\le n}\) 那这里用的肯定是第二种,所以再反演那就是 \(g(n)=\sum_{i\le n}c_{n,i}f(i)\),这里的 \(c_{n,i}\) 只是一个我们用来占位的系数,它是多少不重要,重要的是这个形式,因为 \(f\) 的含义就是“恰好”,通过这个形式就能发现我们的 \(g\) 的意义是“至多”。

换言之我们做的容斥实质上是:钦定一个 \(V\subset S\),然后计算“至多只有 \(V\) 内的条件被满足”的方案数,我们发现这和上面我们最终得到的 \(f(V)\) 是完全一致的!

容斥系数的问题也能得到解决,我们知道二项式反演里的反演系数是 \((-1)^{n-i}\) 在这里也就是 \((-1)^{|S|-|V|}\),但还是因为你是两个 \((-1)^{|S|-|V|}\) 相乘所以你可以认为容斥系数就是 \((-1)^{|V|}\)

OK,现在我们建立了一个快速推出这类容斥的机制,它并不需要太多思考。然后我们继续进入求这个三重和式的环节。

首先就是说 \(S\) 到底是什么不重要,我们只关注有多少个 \(S\),那么我们求的就是:\(\sum_{a,b}2^{n-1-|a\cup b|}f(a)f(b)\)

考虑变成 \(2^{n-1-|a|-|b|+|a\cap b|}\),我们可以把 \(2^{n-1}\) 提出去,然后你相当于要把每个 \(\frac{f(a)f(b)}{2^|a|2^{|b|}}\) 算到 \(2^{|a\cap b|}\) 次。

这就是一个很常见的手法了,前面我们把一个只关注次数不关注具体是什么的 \(S\) 转化了一下;现在我们逆过去,把一个次数强行附上一个集合意义:其实也就是算:

\[\sum_{a,b}\sum_{c\subset a\cap b}\frac{f(a)f(b)}{2^{|a|+|b|}} \]

我们完全可以再来一次,重新定义 \(f(a):=\frac{f(a)}{2^{|a|}}\),这样会好看很多。

交换求和顺序:

\[\sum_{c}\sum_{c\subset a,b}f(a)f(b) \]

枚举 \(c\),然后 \(c\) 中的元素一定都是 \(a,b\) 中的,这部分的话直接会有 \(4^{-|c|}\) 的贡献(其实容斥系数也有,但是 \((-1)^{2|C|}=1\)),考虑把这些位置拿走会形成若干段,\(a-c\)\(b-c\) 可以随便从这些段里随便挑。

如果设 \(g(n)\) 是说在排列长度为 \(n\) 的情况下求 \(\sum_{a}f(a)\) 那么我们考虑,确定 \(c\) 以后,所有的 \(f(a-c)f(b-c)\) 其实就是说,如果有一个长度为 \(k\) 的段,那么我们乘上 \(g^2(k)\),那么方便起见令 \(g(n):=g^2(n)\)

其实还有点不对!因为我们最开始要把 \(n\) 个数先分配到这些段里,有点感觉的话会意识到这是一个 EGF 卷积,所以应该令 \(g(n):=\frac{g(n)}{(n!)^2}\) 然后 EGF 卷积(下面是平方,因为你要对两个排列分别分配)。

而所有 \(\{1,2,...,n-1\}\) 的子集都可以看作一条从 \(0\) 不断往大的数跳,跳到 \(n\) 的路径;你经过的所有点(\(0,n\) 除外)就构成了一个子集,而我们从 \(i\) 跳到 \(j\) 就会带来 \(\frac{g(j-i)}{4}\),这个 \(4\) 在“枚举c”的时候就讲过原因。

如果能求出 \(g\) 那么显然就可以分治 NTT 了,接下来我们考虑如何求 \(g\)

其实求 \(g\) 的思想是一模一样的,因为 \(g(n)\) 要枚举所有 \(\{1,2,...,n-1\}\) 的子集作为 \(a\),依然还是路径;你考虑 \(a\) 确定了以后的方案数,因为把 \(a\) 这些位置去掉以后都是大于号,也就是说你只要决定把每个数分配到哪些段就够了,这就是更裸的 EGF 卷积了,\(i\rightarrow j\) 的贡献就是 \(\frac{1}{(j-i)!}\),显然也可以分治 NTT。

另外我们发现每条路径都会多乘上一个 \(4^{-1}\),最后要记得乘回去;求 \(g\) 那里也是一样,你每跳一次都会有 \((-1)\)\(2^{-1}\) 在,但最后会多算一次。

时间复杂度 \(O(n\log^2 n)\),分治 NTT 也可以利用多项式求逆做到 \(O(n\log n)\)

记录

29. Cards

首先洗牌的过程在诈骗,实质上每次就是说每张牌都有 \(\frac{1}{m}\) 的概率成为第一张牌。

\(x_i\) 是一个 \(0/1\) 变量表示第 \(i\) 轮是否王牌在上,则有:\(E((x_1+x_2+...+x_n)^k)\),把这个东西暴力展开,用期望线性性,相当于求所有的 \(E(x_{i_1}x_{i_2}...x_{i_k})\) 的和。

设集合 \(\{i_1,i_2,...,i_k\}\) 的大小是 \(a\) 则它的 \(E\) 显然是 \(m^{-a}\),现在问题变成了有多少个这样的 \(E\) 在展开后的和式,换言之我们枚举 \(i\) 然后变成了计数问题:\(k\) 个空,每个空可以填 \([1,m]\),问多少种方法使得恰好有 \(i\) 个数出现了。那么首先选颜色的方案数是 \(\dbinom{n}{k}\)\(\dbinom{n}{1\sim k}\) 可以 \(O(k+\log p)\) 预处理。

考虑 egf 卷积,也就是求 \((e^x-1)^{i}\)\(x^k\) 项系数,直接二项式定理展开即可 \(O(k^2)\)

这个展开以后是个卷积形式所以可以优化到 \(O(k\log k)\),另一种思路是我们直接看 \(e^{xi}\) 这个东西代表的是“至多 \(i\) 种颜色”,反演一下就能恰好 \(i\) 种颜色,也是 \(O(k\log k)\)

这个题好像能线性是众所周知的,但我还不会,谔谔。

记录

前置知识:

  1. \(x^k=\sum_{i=0}^{k} {k\brace i}x^{\underline{i}}\)
  2. \({n\brace m}=\sum_{i=0}^{m}(-1)^{m-i}\frac{i^n}{i!(m-i)!}\)
  3. \(\dbinom{a}{b}\dbinom{b}{c}=\dbinom{a}{c}\dbinom{a-c}{b-c}\)(考虑两边的组合意义)
  4. \(O(k)\)\((1\sim k)^{-1}\),以及利用线性筛 \(O(k)\)\((1\sim k)^{k}\)

首先我们把原问题转成一个数数问题:也就是提出 \(m^{-n}\),求 \(\sum_{i=1}^{k}i^n\dbinom{n}{i}(m-1)^{n-i}\)

\(m=1\) 时答案恒为 \(n^k\);以下我们假设 \(m\gt 1\)

由于在 \(n\le k\) 的时候上述式子可以 \(O(n)\) 计算,以下我们再假设 \(n\gt k\)

现在我们的任务是得到一个 \(O(k)\) 做法。

首先将 \(i^n\) 替换成下降幂形式:

\[\sum_{i=1}^{n}\dbinom{n}{i}(m-1)^{n-i}\sum_{j=0}^{k}{k\brace j}i^{\underline{j}} \]

把下降幂转为组合数形式:

\[\sum_{i=1}^{n}j!\dbinom{n}{i}(m-1)^{n-i}\sum_{j=0}^{k}{k\brace j}\dbinom{i}{j} \]

交换求和顺序:

\[\sum_{j=0}^{k}j!{k\brace j}\sum_{i=1}^{n}\dbinom{n}{i}\dbinom{i}{j}(m-1)^{n-i} \]

运用等式 \(3\)

\[\sum_{j=0}^{k}j!{k\brace j}\dbinom{n}{j}\sum_{i=1}^{n}\dbinom{n-j}{i-j}(m-1)^{n-i} \]

现在来看后面的内容,首先当 \(i\lt j\) 的时候组合数取值为 \(0\),因此可以改写成:

\[\sum_{i=j}^{n}\dbinom{n-j}{i-j}(m-1)^{n-i} \]

我们枚举 \(i-j\)

\[\sum_{d=0}^{n-j}\dbinom{n-j}{d}(m-1)^{n-(d+j)} \]

\(p=(m-1)^{-1}\),则:

\[\sum_{d=0}^{n-j}\dbinom{n-j}{d}p^{(d+j)-n} \]

\(p^{j-n}\) 提出:

\[p^{j-n}\sum_{d=0}^{n-j}\dbinom{n-j}{d}p^d \]

由二项式定理,求和结果为 \((1+p)^{n-j}\)

现在我们得到了 \(p^{j-n}(1+p)^{n-j}\),令 \(q=p^{-1}=(m-1)\),我们得到 \(q^{n-j}\times (1+p)^{n-j}=(q+qp)^{n-j}=(1+q)^{n-j}=m^{n-j}\)

因此第二重和式可以被极大简化,现在回到原式:

\[\sum_{j=0}^{k}j!{k\brace j}\dbinom{n}{j}m^{n-j} \]

\(m^n\) 提出,重新定义 \(p=m^{-1}\),则有:

\[m^n\sum_{j=0}^{k}j!{k\brace j}\dbinom{n}{j}p^j \]

注意到在最开始的时候我们为了将概率转为求和,曾经乘上了 \(m^{-n}\),现在其与 \(m^n\) 正好抵消。

此时 \(O(k\log k)\) 已经可以求第二类斯特林数的一整行了,但这还不够快。


只要斯特林数还活着就不太可能 \(O(k)\),因此我们把斯特林数再次拆开,运用式 \(2\)(其实求第二类斯特林数的一整行就是依赖这个式子):

\[\sum_{j=0}^{k}j!\dbinom{n}{j}p^j\sum_{i=0}^{j}(-1)^{j-i}\frac{i^k}{i!(j-i)!} \]

在交换求和顺序前,有一步非常重要:最左侧的 \(j!\) 和内测的 \(\frac{1}{i!(j-i)!}\) 实质上构成了 \(\dbinom{j}{i}\)

\[\sum_{j=0}^{k}\dbinom{n}{j}p^j\sum_{i=0}^{j}(-1)^{j-i}i^k\dbinom{j}{i}\\ =\sum_{i=0}^{k}i^k\sum_{j=i}^{k}\dbinom{n}{j}\dbinom{j}{i}(-1)^{j-i}p^j\\ =\sum_{i=0}^{k}i^k\dbinom{n}{i}\sum_{j=i}^{k}\dbinom{n-i}{j-i}(-1)^{j-i}p^j \]

同样来考察内层,这次我们把 \((-1)^{j-i}p^j\) 先整理得好看一点:把 \((-1)^i\) 提到外层,内层变成 \((-p)^j\),不妨重新定义 \(p:=(-p)\)

\[\sum_{j=i}^{k}\dbinom{n-i}{j-i}p^j \]

运用和第一次处理内层和式一样的手法,首先枚举差值:

\[\sum_{d=0}^{k-i}\dbinom{n-i}{d}p^{d+i} \]

我们提出 \(p^i\),则变成了:

\[p^i\sum_{d=0}^{k-i}\dbinom{n-i}{d}p^{d} \]

观察内侧,这实质上是一个下指标求和的形式,容易让我们想到拆组合数递推(下指标求和的特殊形就是二项式定理),设这个和式的值是 \(S(i)\),我们将会看到 \(S(k)=1\),接下来,利用 \(S(i+1)\) 推出 \(S(i)\)(因为上指标是 \(n-i\),也就是 \(i\) 越大的时候上指标才会越小):

\[S(i)=\sum_{d=0}^{k-i}(\dbinom{n-(i+1)}{d}+\dbinom{n-(i+1)}{d-1})p^d\\ =\sum_{d=0}^{k-i}\dbinom{n-(i+1)}{d}p^d+\sum_{d=0}^{k-i}\dbinom{n-(i+1)}{d-1}p^d \]

两个部分都和 \(S(i+1)\) 的定义极为接近:观察左半部分,发现其仅多出了 \(d=k-i\) 也就是 \(\dbinom{n-i-1}{k-i}p^{k-i}\) 这一项;观察右半部分,枚举 \(d-1\),则有 \(\sum_{d=0}^{k-(i+1)}\dbinom{n-(i+1)}{d}p^{d+1}\),也就是说它的项数是对的,但是每一项多了一个 \(p\);总而言之,我们得到:

\[S(i)=(1+p)S(i+1)+\dbinom{n-i-1}{k-i}p^{k-i} \]

当求出 \(S(i)\) 后,计算下列内容就是答案:

\[\sum_{i=0}^{k}i^k\dbinom{n}{i}p^iS(i) \]

\(i^k\)\(\dbinom{n}{i}\) 还有 \(p^i\) 都可以 \(O(k)\) 全部求出,\(S(i)\) 有一个长得很像 \(O(1)\) 的递推式,不幸的是有一个恶心的 \(\dbinom{n-i-1}{k-i}\),我们要对 \(k\)\(i\) 去求这个组合数。

观察到这些组合数首先上下差值恒定,且上指标是连续的,这类的 \(O(k)\) 个组合数同样可以在 \(O(k)\) 的时间内求出,只需要我们利用吸收恒等式,设 \(C_i=\dbinom{n-i-1}{k-i}\),首先有 \(C_k=1\),然后得到递推式 \(C_i=\frac{n-i-1}{k-i}C_{i+1}\)

时间复杂度 \(O(k)\)

记录

30. Forbidden Value

假设 \(0\) 处有一个 if 0 以及 \(n+1\) 处有一个 end,然后对整个过程建嵌套的树形结构。

\(f(u)\)\(u\) 子树的答案,我们发现这不是可行的一个方法,因为不同子树间是会互相影响的,我们是想知道递归完一颗子树后变量的确切值的。

因此设 \(f(u,v)\)\(u\) 子树走进去,递归完变量是 \(v\) 的最小值。

维护的话,第一眼考虑线段树合并来维护,审视操作,发现有维护全局加一个值,还有单点求值,全局求最小值;考虑全局加这个操作只打一个整体 tag,这在大多数情况下是可行的,问题出在 seg 合并的时候;所以我们必须要写带 pushdown tag 的 seg 但这样似乎空间有点大,不太想试。

然后考虑转用 dsu on tree 维护,这样写起来很暴力。用 map 维护所有 \(f(u,v)\) 的值,然后可以直接打 tag,全局求最小值的话考虑维护 \(f(u,v)\) 构成的 multiset 就行;主要就是合并的时候用 dsu on tree 一下就可以了;特别注意的是,如果你进入的是一个 if y 的这样一个子树,那么原先的 \(f(u,y)\) 应该清为 \(\infty\),而不是和 \(f(v,y)\)\(\min\)

时间复杂度 \(O(n\log^2 n)\),不过好像这个题的输入形式决定了这个 \(n\) 是顶不到 \(2\times 10^5\) 的,实际跑下来也很快。

记录

31. Hero of Our Time

我第一个想法是考虑 EGF 卷积但这样始终是平方的;换个思路考虑枚举一棵树后加边但这样会有重复计算的情况,且一颗环长为 \(L\) 的树会被算 \(L\) 次;然后猛然发现可以直接枚举环长,然后再用 prufer 的图联通公式这样就 \(O(n)\) 了。

然后不想写高精度所以试了试 python,发现 5000 跑的很慢,需要卡卡常数才能过。

记录

32. Cool Slogans

显然:\(s_i\) 必定为 \(s_{i+1}\) 的后缀,也就是说,整体可以看作一个在 link 树上不断向下走的过程。

显然,一个 endpos 等价类里不可能有两个串被选到;另一方面,给出两个节点,且指定两个串的长度,我们容易 seg 合并维护 endpos 来 \(O(\log)\) 地 check。

这个走的过程很像 dp 状物,考虑设 \(f(u)\)\(u\) 子树内的答案。

问题在于一个节点对应了多个串,这看上去就无法转移。

我们猜测我们只关注所有节点的最长串(以下称代表串),证明如下:

首先最后用的那个串可以替换成所在节点的代表串,然后我们逆着推回去,证明:

\(s\) 是代表串,且 \(a\)\(s\) 的 border,则 \(a\) 一定也是代表串。

为什么只关注 border?因为除了 \(a\) 在最开头出现的情况以外,只要 \(a\) 不是代表串,我们总能把 \(a\) 换成等价类里比它长度大 \(1\) 的一个形如 \(c+a\) 的串。

反证,假设 \(a\) 不是代表串。那么令 \(b=c+a\)\(a\) 是作为 \(s\) 的一个前缀出现的,那么这个 \(a\) 的结尾处也是拥有 \(b\) 的,换言之:只要 \(s\) 出现了,那么 \(c+s\) 也就必定要出现。这可以推导出 \(s\)\(c+s\) 属于一个节点;而 \(s\) 是代表串就说明它是节点里最长的串,矛盾;所以我们证明了 \(a\) 一定也是代表串。

然后就做完啦,dfs 的过程中可以倍增维护最深的 \(y\) 满足 \((x,y)\) 两个节点的代表串是合法的,然后用 \(y\) 以及其往上的信息去更新 \(dp_x\) 即可。时间复杂度 \(O(n\log^2 n)\)

记录

33. 字符串问题

第一眼看上去很复杂,第二眼我们考虑建立 SAM 然后把每个点挂在 parent tree 上。

考虑前 80 分,那么每个 \(A\) 类串向能支配的 \(B\) 类串连边,\(B\) 类串向作为前缀的 \(A\) 类串连边,然后跑拓扑排序最长路就行,有环的情况容易判。

第二类边实质上就是 parent tree 对应位置的子树内。

如果有 \(|B|\gt |A|\) 的情况那么我们特判两个串在一个节点的情况,此时按照长度再排序一下。

考虑使用 set 在 dfn 序上(以及每个 parent tree 的节点上)维护所有 vis=0 的位置,对于已经计算完 dp 的位置我们需要在 dfn 序上单点修改区间求 max 来更新答案;然后判环的话可以再搞个单点修改区间求和的 bit 判断(现在发现这个似乎也可以 seg 谔谔)。

然后就大概在 \(1\log\) 的时间内做完了。

AC了后才发现更简单的方法其实是直接按照上面的方法优化建图一下就结束了......似乎建完 SAM 以后都是线性的......

记录

34. Transferring Pyramid

一眼三角形大小不会超过根号,然后卡了一会还是不会暴力啊,遂开摆打 T2。

赛后被点拨了一句按照对角线 dp 就豁然开朗了。只考虑三角形然后从左往右按照对角线 dp 然后设 \(f(i,j)\) 是第 i 条对角线覆盖了末尾 \(j\) 个就行了。

转移 \(f(i,j)\rightarrow f(i+1,j-1)\) 或者 \(f(i+1,k)(k\ge j)\) 这个前缀和优化一下就行。

时间复杂度 \(O(n\sqrt m)\)

记录

35. Quasi-template

考虑利用 SAM 建出 parent tree,再利用 seg 合并求出每个节点的 endpos 集合里的最大相邻间隔,记作 \(p\)

则该等价类里首先合法的串长度都是 \(\ge p\) 的;其次,还有前缀和后缀的问题。

考虑前缀,我们发现我们关注的是该串的最长后缀 \(S\) 满足 \(S\) 也是原串的前缀。显然 \(S\) 一定位于 parent tree 的祖先上。

一个细节是,当这样的 \(S\) 存在于当前节点(首先可以说明一个 endpos 等价类最多只会有一个是原串前缀)的时候,我们要对该等价类中,串长度 \(\ge |S|\) 的部分,和小于 \(|S|\) 的部分分类讨论;因为这两部分串和原串匹配的结果是不一样的。

然后一个等价类至多会给出两个形如 \([l_1,l_2]\leftrightarrow r\) 的区间,代表所有左端点在 \(\in [l_1,l_2]\) 右端点在 \(r\) 的子串;我们知道 \(r\) 可能有多个,方便起见我们定义 \(r\) 是 endpos 集合里的最小值。

考虑后缀,我们反转串重新做一遍前缀的这个过程,然后把得到的信息对应到前缀上,那么会给出两个形如 \(l\leftrightarrow [r_1,r_2]\) 的区间。这里要注意此处的 \(l\) 要与上面得到的区间对应(所以应该我们这里关注 endpos 集合的最大值)。

把区间 \([l,r]\) 视作二维平面上的一个点则上述结果可以离线后扫描线解决;现在计数问题做完了。

考虑求最优秀串,对每个时刻的 seg 套一个 seg 二分得到 \(n\)\(l\) 固定的时候的最优秀结果。然后对这 \(n\) 个结果哈希 + 二分即可。

时间复杂度 \(O(n\log n)\)

posted on 2022-12-03 09:51  Cry_For_theMoon  阅读(303)  评论(3)    收藏  举报