2025 暑假做题记录

CF1310C Au Pont Rouge

\(O(n^2)\) 个子串按字典序排序,我们得到了每个子串的排名 \(rk_{i,j}\)。考虑二分答案串的排名,我们需要考虑有多少种划分方案使标签的排名大于 \(mid\)

\(f_{i,j}\) 代表,考虑到了前 \(i\) 位,划分了 \(j\) 段,每一段子串的最小子串大于 \(mid\) 的方案数。转移时枚举最后一个子串填什么即可,复杂度 \(O(n^2m\log n)\),需要进一步优化。

注意到我们如果刷表转移,即用当前位置 \(i\) 去扩展后面的位置 \(j\) 的话,发现 \(j\) 实际上是一个后缀。这是因为随着子串长度的增加,它的字典序是单增的。因此我们枚举第一个 \(rk_{i+1,j}>mid\)\(j\),随后对 \(j\) 做后缀加即可。这里维护 \(f\) 的差分数组即可,每次到一个位置做一遍前缀和。复杂度 \(O(nm\log n)\),可以通过。

CF616F Expensive Strings

把所有串用特殊字符隔开然后拼起来,我们给新串的每个字符附上一个点权,权值为其所在原串的 \(c_i\)。这样 \(f(s)\) 可以刻画为 \(s\) 在新串中所有出现的位置的点权之和乘以 \(|s|\)

对新串建 SA,根据 \(\operatorname{lcp}\) 的经典结论,有 \(s\) 在新串中的这些出现位置构成一个连续的 \(rk\) 区间,\(|s|\) 的上界就是这个区间的 \(\operatorname{height}\)\(\min\),即 \(\operatorname{lcp}\)。我们肯定希望 \(|s|\) 尽量大,因此直接令 \(s\) 就是这个 \(\operatorname{lcp}\) 即可。至于那个 \(c_i\) 之和,我们可以预处理出按后缀排名的 \(c\) 的前缀和。

现在考虑如何加速枚举区间的过程,用单调栈找出每个位置作为 \(\operatorname{height}\) 最小值的最长连续段,直接更新答案即可,这里用最长连续段是因为这整个段一定会被匹配上,而非可以选择那些 \(c_i<0\) 的位置不匹配。注意特殊处理一个串只出现一遍的情况。

CF587F Duff is Mad

Mike and Friends 的加强版,但是还是有会的可能的。

将所有串拼起来,我们要求的实际上是 \(\sum\limits_{i=l}^r\sum\limits_{j=b_k}^{b_k+len_k-1}[\operatorname{lcp}(b_i,j)\ge len_i]\)。其中 \(b_i\) 为第 \(i\) 个原串在新串中的开始位置,\(len_i\) 为第 \(i\) 个原串的长度。将每一个 \(i\) 所对应的那段合法的 \(rk\) 区间二分出来,令其为 \([X_i,Y_i]\),则式子改为 \(\sum\limits_{i=l}^r\sum\limits_{rk_j=X_i}^{Y_i}\sum\limits_{j=b_k}^{b_k+len_k-1}\)。考虑离线扫描线,遇到一个 \(i\) 就对 \([X_i,Y_i]\) 作区间加,可以 BIT。由于 \(i\)\(rk_i\) 这两维之间毫无关联,因此我们只能暴力枚举 \([b_k,b_k+len_k-1]\),作单点查。

在我们果断放弃树套树与 KDT 之后,考虑根号分治。若 \(len_k\le \sqrt n\),则我们用上面的做法暴力枚举;若 \(len_k>\sqrt n\),由于我们有 \(\sum len_i\) 的限制,因此这样的 \(len_k\) 不超过 \(\sqrt n\) 个。考虑一个更为暴力的做法,我们对于每个这样的 \(k\),开一个 vector,把 \([b_k,b_k+len_k-1]\) 里所有的数插进去后按 \(rk\) 排序,在扫描线的时候可以直接 vector 二分。不难发现 vector 里至多有 \(n\sqrt n\) 个元素,因此这是可以接受的。

总复杂度 \(O(n\sqrt n\log n)\),可过。当然通过调块长可以有更优的复杂度。

8-18 模拟赛 T3

简述题意:有一个长度为 \(n\le 10^5\) 的序列 \(a_i\) 以及一个整数 \(1\le m\le 50\),满足 \(0\le a_i\le 2^m\)。给你一个整数 \(T\le 10^{16}\),求出有多少个 \(1\le t\le T\),使得 \(\bigg((a_1+t)\bmod 2^m\bigg)\oplus \bigg((a_2+t)\bmod 2^m\bigg)\oplus\dots\oplus\bigg((a_n+t)\bmod 2^m\bigg)=S\),其中 \(S\) 是给定的一个值。

注意到 \(\bmod 2^m\) 等价于保留二进制的低 \(m\) 位,因此合法的 \(t\) 关于 \(2^m\) 会形成周期,因此我们只需要考虑 \(\min(2^m-1,T)\),内的 \(t\)。令 \(dp(R)\) 代表限制 \(t\le R\) 的合法 \(t\) 个数,实际上答案就是 \(dp(2^m-1)\times \frac{T}{2^m}+dp(T\bmod 2^m)\),当然注意如果 \(t=2^m\) 转一圈回到原来的位置仍合法的话,我们就多算了一位,因此要减去一。

考虑快速计算 \(dp(R)\)。我们发现某一位的 \(t\)\(0/1\) 是否合法,其实只取决于这一位 \(1\) 的个数,但是上一位的 \(t\) 有可能会通过进位对这一位造成影响,因此我们需要记录某一个 \(a_i\) 是否进位。需要维护的信息过于复杂,考虑压缩状态,实际上我们发现加上同一个 \(t\) 之后,会造成进位的 \(a_i\) 一定是「按这一位后面的数排序之后的一段后缀」,即数大的才有可能进位。因此我们只关心上一位对这一位造成了 几个进位,就可以通过排序后的后缀得到哪些 \(a_i\) 有进位。

我们先将所有位后面的数排序。令 \(sa_{j,i}\) 代表,现在只考虑 \(a_i\) 的二进制后面 \(j\) 位,其它扔掉,然后按照大小排序的第 \(i\) 大的编号。这可以通过利用 \(sa_{j-1,i}\) 做一遍值域为 \(2\) 的基数排序得到。再令 \(cnt1_{j}\) 代表有多少个 \(a_i\)\(j\) 位为 \(1\)。以上便是所有预处理,现在考虑设计数位 dp 状态。

\(dp_{l,x,0/1}\) 代表,考虑到了低 \(l\) 位,\([0,l-1]\) 位已符合要求,且第 \(l-1\) 位对第 \(l\) 位造成了 \(x\) 个进位,且当前的 \(t\) 是否已经超过了 \(R\) 的上界,\(t\) 的方案数。初值为 \(dp_{0,0,0}=1\),答案就是考虑枚举第 \(m-1\) 位对第 \(m\) 位的进位数,当然不能超上界,即 \(\sum\limits_{i=0}^ndp_{m,i,0}\)。考虑刷表转移,即用 \(dp_{l,x,0/1}\) 去更新第 \(l+1\) 位的 \(dp\) 值。

再令 \(s\) 代表在进了 \(x\) 位之后,第 \(l\)\(1\) 的个数;令 \(c\) 代表在进了 \(x\) 位之后,\(x\) 位产生的进位个数。 转移的时候,我们先枚举 \(l,0/1\),再枚举 \(x\),这是因为我们需要动态更新 \(s,c\)。考虑当前这位 \(t_l\)\(0/1\) 能否产生贡献,先考虑 \(t_l=0\) 的情况,也就是说此时这一位的 \(1\) 个数没变,即 \(s\)。那么转移就是 \(dp_{l+1,c,type}\leftarrow dp_{l,x,0/1}\),转移条件是 \(S_l\equiv (s\bmod 2)\);再考虑 \(t_l=1\) 的情况,此时这一位 \(1\) 的个数发生了「取反」,即变成了 \(n-s\),那么转移就是 \(dp_{l+1,s+c,type}\leftarrow dp_{l,x,0/1}\),转移条件是 \(S_l\equiv ((n-s)\bmod 2)\)

在转移结束后,我们要动态更新 \(s\)\(c\),具体来说考虑第 \(l-1\) 位向 \(l\) 多进了一位,那么我们就需要考虑 \(sa_{l-1,x+1}\)(上文提过,造成进位贡献的是按照后缀大小排序的)的这一位是否为 \(1\),如果这一位为 \(1\),那么进位之后第 \(l\) 位的 \(1\) 就没了,因此 \(s\) 减一,\(c\) 加一;否则 \(s\) 加一。

8.18 模拟赛 T4

简述题意:给你大小为 \(n\le 5000\) 的一个带点权树,点权为 \(a_i\)。给你 \(T,lim\le 10^5\),你需要在 \([0,T]\) 中选择一个数 \(c\),并令所有 \(a_i\leftarrow (a_i+c)\bmod lim\)。之后你要在树上选若干条不交路径,若你选择了 \(k\) 条且点权和为 \(s\),你的得分为 \(\frac{s}{k+1}\)。找出一种选 \(c\) 和选路径的方案,最大化得分。

取模很难有什么性质,于是考虑枚举 \(c\)。此时点权确定,问题转换成一个经典的分数规划问题。我们二分答案 \(mid\),考虑 check 是否存在 \(\frac{s}{k+1}\ge mid\),将式子变形有 \(s-k\times mid\ge mid\),不难发现这等价于每选出一条路径,把这条路径的点权和减去 \(mid\),然后要求总和 \(\ge mid\)。此时我们就不关心路径条数了,可以考虑直接 dp。令 \(f_{u,0/1/2}\) 代表考虑到子树 \(u\),当前点不选为路径/选为单链/选为双链的最大总和,转移显然。

于是我们可以在 \(O(n)\) 的复杂度内完成一次 check。复杂度为 \(O(lim\times n\times \log(W))\),无法通过。注意到对于一个 \(c\),如果所有的 \((a_i+c)\) 都小于 \(lim-1\),那么我们将 \(c\) 加一显然更优,因此有用的 \(c\) 只会是 \(\min(lim-1-a_i,T)\) 的形式,这样我们只需要枚举 \(O(n)\)\(c\),复杂度 \(O(n^2\times \log(W))\),无法通过。

一个强剪枝是,对于当前的 \(c\),我们在二分之前先 check 一下当前的 \(ans\),如果返回 \(1\),那么将二分左端点设为 \(ans\),否则直接跳过这个 \(c\)。这是因为根据单调性如果 check \(ans\) 没了,那么不可能取到更优的结果的。也就是说我们只需要二分从第一个枚举的 \(c\) 开始的最长上升子序列次。复杂度 \(O(n^2\times \log(W))\) 加极小常数,无法通过。

注意到出题人可以构造二分出的答案单增的 \(c\) 序列让你仍然需要二分 \(O(n)\) 次。考虑最终优化,我们对这个序列进行 random_shuffle,然后去做同样的事情。此时序列被随机打乱,有结论随机序列的 LIS 期望为 \(O(\log n)\),复杂度 \(O(n^2+n\log(n)\times \log(W))\),可以通过。

ABC262Ex Max Limited Sequence

区间 \(\max\) 的限制,实际可以刻画为两点:区间上界小于等于 \(\max\)、区间内至少有一个 \(\max\)。我们先解决掉第一个限制,不难发现我们只需要每次对区间做 \(\operatorname{chkmin}\),可以通过将区间按 \(\max\) 降序排序来转换为区间推平。令 \(lim_i\) 代表第 \(i\) 个位置的上界,我们每次将所有 \(lim_i\) 相同的位置拎出来,一块针对第二个限制 dp。

令当前处理的 \(lim_i=x\),这些 \(i\) 构成的位置为 \(p_1,p_2,\dots,p_m\)。我们其实只关心 \(a_{p_i}\) 填的是否等于 \(x\),于是设 \(f_{i,j}\) 代表考虑到了 \(p_m\),上一个 \(a_{p_j}=x\) 的位置是 \(p_{j}\) 的方案数。对于一次转移,先特殊处理 \(f_{i,i}=\sum f_{i-1,j}\),朴素转移即为 \(f_{i,j}=f_{i-1,j}\times x\),考虑如何处理区间的限制。我们将区间挂在右端点上转移。枚举所有 \([l,i]\),并对所有 \(j<l\)\(f_{i,j}\) 推平成 \(0\) 即可。考虑用线段树维护 \(f_i\),发现三个操作等价于全局和、全局乘、区间清零。复杂度 \(O(n\log n)\)

AGC030F Permutation and Minimum

原问题可以刻画为,将 \([1,2n]\) 这些点按顺序排成一列,将两两之间连线,要求每个点恰被一条线连接,一条线形成的 \(b_i\) 就是左端点的值。一条线有三种情况:两端点均被固定、只有一个端点被固定、都未被定序。注意到除了最后一种之外其他线都已被定序,因此只需要在算完连线方案后乘上未被定序线个数的阶乘即可。考虑如何计算连线方案,即定义两组连线方案不同,当且仅当存在一个位置不再作为左端点/右端点、或有一个端点被固定的线中另一端点发生变化。

从大到小确定连线方案,即用小数去和未匹配的右端点连线。令 \(f_{i,j,k}\) 代表,我们考虑到了 \(\ge i\) 的所有数,目前还有 \(j\) 个未被匹配的未固定右端点,\(k\) 个未被匹配的固定右端点。转移显然,根据当前值是否被固定以及是否匹配、与是否被固定的数匹配分讨即可。复杂度 \(O(n^3)\)

[AGC013E] Placing Squares

考虑这个填正方形的组合意义,等价于我们将原序列划分成若干段,并在每一段中放可以重合的黑球、白球(用方案数刻画面积),有些位置之间不能划分开,求方案数。然后就可以令 \(f_{i,0/1/2}\) 代表考虑到位置 \(i\)\(i\) 所在段目前已经放了 \(0/1/2\) 个球的方案数,将转移写出来之后发现是线性转移。分成 \(m\) 段做分段矩乘即可。

有基于推式子的非组合意义做法,我们直接令 \(f_i\) 代表考虑到位置 \(i\) 并强制在 \(i\)\(i+1\) 中间划分开的方案数,有转移 \(f_{i+1}=\sum\limits_{j=0}^{i}f_j\times (i-j+1)^2\),当 \(i\) 是特殊点时 \(f_i=0\)。考虑将最后一项提出来,有 \(f_{i+1}=\sum\limits_{j=0}^{i-1}f_{j}(i-j)^2+2\times \sum\limits_{j=0}^{i-1}f_j(i-j)+\sum\limits_{j=0}^{i-1}f_j+f_i\)。分别把四项放到矩阵里,可以直接分段矩乘。

CF908G New Year and Original Order

一手拆贡献,数位 \(d\) 的贡献是「有多少数按数位排序后该数位后面有 \(i\) 个值」倍的 \(10^i\)。但是直接做不太好设计状态。

这样没有前途在于,我们相当于在算一列的贡献。一个 Trick 是考虑将数拆成若干 \(111\dots1\) 相加的形式。我们发现对于一个已经排序后的数拆成这样相加的形式,那么每一行的贡献就是若干个一,而注意到第 \(i\)\(1\) 的个数就是数位中 \(\ge i\) 的个数,因此我们可以通过数位 dp 转换成对每一行的贡献。

对于每个 \(i\),求出有多少个数满足恰有 \(i\) 个数位大于等于 \(d\),贡献就是 \(111\dots1\)\(i\)\(1\)。直接令 \(f_{i,j,0/1}\) 代表考虑到了第 \(i\) 位,恰有 \(j\) 数位大于等于 \(d\),是否贴上界。转移显然。复杂度 \(O(700^2\times 10\times 10)\)

CF1773G Game of Questions

\(f_s\) 代表当前存活集合为 \(s\),该人存活概率,答案为 \(f_{2^m-1}\)。我们发现转移的时候无法确定这个题目之前是否被用过了,因此非常棘手。这个题的 Trick 在于,考虑如果一个题目在存活集合变为 \(s\) 之前用过了,现在我们考虑再用一次,那实际上不会对 \(s\) 造成任何变化。因此我们只需考虑选完之后会对 \(s\) 造成变化的集合。

\(g_{s,t}\) 代表有多少种题目选完后可以实现存活集合从 \(s\) 变成 \(t\)。那么转移即为 \(f_s=\frac{\sum\limits_{t\subset s}f_t\times g_{s,t}}{n-g_{s,\varnothing}-g_{s,s}}\),分子代表恰将 \(s\) 变为 \(t\) 的概率,分母代表实际使 \(s\) 产生改变了总题目数。初值为对于所有的 \(g_{s,\varnothing}+g_{s,s}=n\),若集合 \(s\) 包含该人,则 \(f_s=1\)

现在考虑如何求出 \(g_{s,t}\),题目的选取条件等价于 \(s_i\&s=t\),因此我们可以考虑钦定 \(s\) 集合外部的一个 \(x\),并随意的考虑 \(x\) 是否被 ban 掉即可。转移即为 \(g_{s,t}=g_{s\cup x,t}+g_{s\cup x,t\cup x}\),其中 \(x\) 是任选的。

P3647 [APIO2014] 连珠线

一个重要的性质是蓝链是由若干长度为 \(2\) 的链组成的,且这些链只会在端点处有交。长度为 \(2\) 的链只有两种,一种是 \(fa_u,u,v\in son_u\) 的形式,另一种是 \(v_1\in son_u,u,v_2\in son_u\) 的形式。当然我们可以根据这两种链做 \(f_{u,0/1/2}\) 的经典 dp,就是考虑 \(u\) 作为非蓝链上点/第一/第二种形式。但是我们可以发现如果树中同时出现两个 \(v_1\in son_u,u,v_2\in son_u\) 的形式是不合法的,因为蓝链中点只能是在基于两边端点原来存在的基础上插入,我们很难使转移避开这种情况。

重新调整结论,树的蓝链只由若干长度为 \(2\) 的形如 \(fa_u,u,v\in son_u\) 的单链以及至多一条 \(v_1\in son_u,u,v_2\in son_u\) 的形式。 由于第二种形式只会出现一次,可以发现如果我们选择恰当的根,那么会有一个儿子被旋到上面使整棵树只存在第一种情况。因此我们可以假定每个点作为根,做一遍只存在第一种情况的树形 dp。令 \(f_{u,0/1}\) 代表考虑到 \(u\) 子树,\(u\) 这个点是否作为蓝链中点。这个状态以及转移的合法性在于,两条长度为 \(2\) 的蓝链不会出现边重合的情况,因此边不会被重复算到。有转移 \(f_{u,0}=\sum\max(f_{v,0},f_{v,1}+w)\)\(f_{u,1}=f_{u,0}+\max(f_{v,0}+w-\max(f_{v,0},f_{v,1}+w))\)。后面那个转移的意思是,我们将一个点作为蓝链端点,并要最大这个贡献的改变量。则一个根的答案为 \(f_{root,0}\),因为根作为深度最小的点,不能为蓝链中点。

当然这样暴力做是 \(O(n^2)\) 的,考虑用换根 dp 优化这件事情。令 \(g_u\) 代表以 \(u\) 作为整棵树的根的答案,对于一次从 \(u\)\(v\in son_u\) 的转移,贡献分为两部分,一部分是 \(f_{v,0}\) 本身,另一部分是 \(u\) 抛掉 \(v\) 子树后的其他部分的贡献。我们令 \(h_{u,v,0/1}\) 代表这一点,\(0/1\) 代表是否作为蓝链中点。转移分为两部分,一部分是 \(u\) 父亲外面,可以通过 \(h_{fa,u,0/1}\) 得到,另一部分是 \(u\)\(v\) 的儿子,可以记录之前那个改变量的最大次大位置实现。复杂度 \(O(n)\)

CF1765C Card Guessing

拆贡献,期望猜对次数等于每次猜对的概率之和。不难发现一次猜花色只需要关心其前面 \(\min(k,i-1)\) 张牌出现次数最小花色的出现次数 \(j\),则该点被猜中的情况就有 \(n-j\) 种选法。令 \(g_{i,j}\) 代表选了 \(i\) 张牌,花色最小出现次数为 \(j\) 的方案数,我们不知道怎么选花色因此不太好转移。考虑拆成背包,令 \(f_{i,j,k}\) 代表考虑到了第 \(i\) 种花色,选了 \(j\) 张牌,花色最小出现次数为 \(k\) 的方案数。转移就是枚举下一种颜色的出现次数 \(c\),乘上一个组合数系数即可。这里我们认为相同花色不同牌是本质不同的,那么乘上的组合数就是 \(C_{j+c}^c\times C_{n}^i\times i!\)。那么特殊处理 \(g_{i,0}\) 后易得 \(g_{i,j}=f_{4,i,j}\)。下面考虑处理计数原序列,令 \(h_i\) 代表长度为 \(i\) 的本质不同卡牌序列,有 \(h_i=\sum\limits_{j=0}^n g_{i,j}\)。则第 \(i\) 次抽牌的最终概率就是 \(\frac{\sum\limits_{j=0}^ng_{\min(k,i-1),j}\times (n-j)}{h_{\min(k,i-1)+1}}\)。我们发现这里我们并没有处理前 \(\min(k,i-1)\) 张牌之前的牌的贡献,这是因为分子分母需要乘的贡献相同,因此我们可以不再考虑了,这一点和 CF1773G 类似。注意特判第一次抽牌的概率为 \(\frac{1}{4}\)。复杂度 \(O(n^3)\)

CF1656H Equal LCM Subsets

\(\text{lcm}\) 下放到质因子上。令 \(\alpha_{x,p}\) 代表数 \(x\) 中质因子 \(p\) 的次数,则 \(\text{lcm}(S_A)=\text{lcm}(S_B)\) 等价于对于每个质因子 \(p\),满足 \(\max\limits_{x\in S_A}\alpha_{x,p}=\max\limits_{y\in S_B}\alpha_{y,p}\)。最大值相等不太好刻画,一个思路是用两个不等式来刻画,即 \(\text{lcm}(S_A)\mid\text{lcm}(S_B),\text{lcm}{S_B}\mid\text{lcm}(S_A)\)。由于对称性,这里只分析 \(\text{lcm}(S_A)\mid\text{lcm}(S_B)\)。对于每个 \(x\in S_A,y\in S_B,p\in \text{Prime}\),有 \(\alpha(x,p)\le \alpha(y,p)\),即 \(\alpha(x,p)=\min(\alpha(x,p),\alpha(y,p))\)。将式子移项,有 \(\alpha(x,p)-\min(\alpha(x,p),\alpha(y,p))=0\)。这个等式是下放到质因子后的结果,考虑将每个质因子的式子作为指数乘起来,有 \(\prod\limits_{p\in \text{Prime}}p^{\alpha(x,p)-\min(\alpha(x,p),\alpha(y,p))}=\prod\limits_{p\in \text{prime}}p^0=\frac{x}{\gcd(x,y)}=1\)。这个式子看着舒服多了,考虑对于 \(x\) 将所有 \(y\) 的上式 \(\gcd\) 起来,有 \(\gcd\limits_{y\in S_B}\frac{x}{\gcd(x,y)}=1\)。分析完了 \(\text{lcm}(S_A)\mid\text{lcm}(S_B)\) 的情况,那么 \(\text{lcm}(S_B)\mid\text{lcm}(S_A)\) 同理。综上,我们得到了 \(\text{lcm}(S_A)=\text{lcm}(S_B)\) 的另一个充要判断形式:对于任意 \(x\in S_A\),有 \(\gcd\limits_{y\in S_B}\frac{x}{\gcd(x,y)}=1\);对于任意 \(y\in S_B\),有 \(\gcd\limits_{x\in S_A}\frac{y}{\gcd(y,x)}=1\)。这个转换有两个好处,一个是我们将比较难处理的 \(\text{lcm}\) 的转换成了 \(\gcd\) 的形式,另一个是假如某一个集合被确定,我们可以通过上式判断另一集合中的某个元素是否能存在于答案中,即判断那个 \(\gcd\) 是否为 \(1\)。这提供给我们一个构造答案的思路。

具体来说,我们先假定 \(S_A=A,S_B=B\),即集合都取满。接着我们分别枚举 \(S_A,S_B\) 中的每一个元素,并根据上式判断该元素能否出现在答案中,如果不能就把该元素从对应集合删去。重复执行这一过程直到不存在能删的元素或者 \(\max(|S_A|,|S_B|)=0\),对于第二种情况显然无解。考虑分析复杂度。每次我们删去一个元素后,由于该集合形态发生变化,因此需要枚举另一集合内的所有元素重新 check 一遍。总共至多会删 \(O(n)\) 个元素,每次删完之后有至多 \(O(n)\) 个元素的 check,暴力 check 需要枚举集合内的所元素并计算 \(\gcd\),因此需要 \(O(n\log W)\) 的时间,总复杂度为 \(O(n^3\log W)\),无法通过。

发现复杂度瓶颈在于快速如何计算 \(\gcd\limits_{y\in S_B}\frac{x}{\gcd(x,y)}\) 以及 \(\gcd\limits_{x\in S_A}\frac{y}{\gcd(y,x)}\)。考虑开两棵线段树,大小为 \(n\times m\)。对于第一棵线段树,我们将其分为 \(n\) 块,每块长度为 \(m\),其中第 \(i\) 块的第 \(j\) 个位置存储的是 \(\frac{A_i}{\gcd(A_i,B_j)}\),同时维护区间 \(\gcd\);对于第二棵线段树,我们将其分为 \(m\) 块,每块长度为 \(n\),其中第 \(i\) 块的第 \(j\) 个位置存储的是 \(\frac{B_i}{\gcd(B_i,A_j)}\),同时维护区间 \(\gcd\)。对于查询 \(\gcd\limits_{y\in S_B}\frac{x}{\gcd(x,y)}\),我们找出第一棵线段树中 \(x\) 所在的那个块的范围,跑区间 \(\gcd\) 即可;对于另一个查询,同样找出第二棵线段树的对应块即可。考虑维护删除操作,不难发现我们只需要找到线段树中与该点有关的所有叶子结点,将其单点修改成 \(0\) 即可。

分析复杂度,对于每次 check,需要跑一遍线段树区间 \(\gcd\),复杂度为小常数 \(O(\log n\log W)\);对于每次删除,线段树上与一个元素有关的叶子至多有 \(O(n)\) 个,对这些点进行单点改,复杂度同样为小常数 \(O(\log n\log W)\)。综上,我们在 \(O(n^2\log n\log W)\) 的复杂度内完成了此题。

U598409 愿与愁(castleintheair)

\(c_i=\sum\limits_{j<i}[a_j>a_i]\) ,我们不难证明 \(a\)\(c\) 构成双射。考虑对 \(c\) 计数有什么好处,此时权值分母,即为逆序对个数 \(\sum c_i\);权值分子,根据经典结论为 \(\max c_i\)。于是转换成求 \(\frac{\sum c_i}{\max c_i}\) 的期望。考虑固定 \(\max c_i=k\),求出所有 \(\sum c_i\) 的总和。令 \(f_i\) 为所有 \(\max\le i\)\(c\) 的个数,\(g_i\) 为所有 \(\max\le i\)\(c\)\(\sum c_i\) 之和。则答案为 \(\sum\limits_{i=1}^k \frac{g_i-g_{i-1}}{i}\times \frac{1}{f_k}\)

先求 \(f_i\)。我们有 \(0\le f_j\le\min(j-1,i)\),因此对于前 \(i\) 个数贡献为 \(i!\),后面贡献为 \((i+1)^{n-i}\),即 \(f_i=i!(i+1)^{n-i}\)

再求 \(g_i\),直接求所有 \(\sum c_i\) 的总和不太好做,经典套路是先算出期望,再乘以 \(f_i\)。由期望线性性,考虑将 \(c_j\) 拆开,发现每个 \(c_j\) 的期望是从 \([0,\min(j-1,k)]\) 中等概率选取数的期望,即 \(\frac{\min(j-1,k)}{2}\)。等差数列求和即可。

此时复杂度为 \(O(n\log n)\),无法通过。瓶颈在于 \((i+1)^{n-i}\) 的快速幂。我们令 \(n\leftarrow n+1\),那么等价于我们需要快速计算 \(i^n\)\(i^{-i}\)。对于 \(i^n\),注意到这是一个积性函数,我们预处理出所有质数的 \(i^n\) 后线性筛即可。对于 \(i^{-i}\),考虑先求出 \(i^i\),再根据前缀积线性求序列逆元。我们同样考虑线性筛。令 \(h_i=i^i\)。假如我们已知 \(h_p,h_q\) 的值,其中 \(p\) 是最小质因子,考虑算出 \(h_{pq}=(pq)^{pq}=h_p^q\times h_q^p\)。分成两部分处理,对于第一部分,发现底数是 \(<\sqrt n\) 的质数,考虑预处理出这些质数的光速幂,即可做到 \(O(\frac{\sqrt n}{\ln n}\times \log n)=O(n)\);对于第二部分,考虑递推出每个质数的 \(h_q^{p_i}\),然后用 \(h_q^{p_{i-1}}\) 乘上一个 \(h_q^{p_i-p_{i-1}}\) 即可,后面那个可以直接快速幂。这是因为根据 prime-gap 那套理论,可以证明这个质数差在质数个数下是均摊 \(O(1)\) 的。

至此,我们在 \(O(n)\) 的复杂度内解决了此题。

P3175 [HAOI2015] 按位或

拆贡献,对于一个二进制位,其变为 \(1\) 之后就不会变了,因此考虑该位变为 \(1\) 的时刻 \(t\),则答案为 \(E(\max t_i)\)。不太好设计跟 \(\max t_i\) 有关的 dp 转移,考虑 min-max 容斥,根据期望的线性性,可以直接拆成 \(\sum\limits_{U\in S}-1^{|u|+1}E(\min\limits_{i\in U}t_i)\)。我们换一种方式描述 \(E(\min t_i)\):你每个时刻向箭靶射一箭,射中的概率为固定值 \(p\),求期望最早射中时刻,显然答案为 \(\frac{1}{p}\)。考虑原问题,因为要求最早被选中的 \(i\in U\) 的期望时刻,因此只要选中的数与 \(U\) 有交就能造成贡献。令 \(f_U\) 为所有与 \(U\) 有交的二进制数的 \(p_i\) 之和,根据上面的转换有 \(E(\min\limits_{i\in U}t_i)=\frac{1}{f_U}\)。问题在于如何求出 \(f_U\),可以用 \(1\) 减去与 \(U\) 无交的 \(p_i\) 之和,即 \(1\) 减去 \(U\) 补集的子集和。sosdp 即可。复杂度 \(O(n2^n)\)

P5643 [PKUWC2018] 随机游走

考虑每个点被走到的时刻 \(t_i\),答案为 \(E(\max t_i)\)。一手 min-max 容斥,转换为 \(E(\min\limits_{i\in U}t_i)\)。令 \(f_{u,s}\) 代表,从点 \(u\) 开始随机游走,走到 \(s\) 中任何一个点的期望时间。答案就是 \(\sum\limits_{U\subset S}-1^{|U|+1}f_{x,U}\),可以将 \(f_{x,U}\) 乘上系数然后放进 sosdp 里跑出子集和,这样查询就是 \(O(1)\) 的了。考虑如何求 \(f_{u,s}\),首先显然有对于 \(u\in s,f_{u,s}=0\),另一个朴素的转移是 \(f_{u,s}=1+\sum\limits_{(u,v)\in E}\frac{f_{v,s}}{\text{deg}_u}\)。可以对于每个 \(s\) 跑一遍高斯消元,总复杂度为 \(O(2^nn^3+qn)\),可以通过不卡常的 P4321,无法通过本题。

仔细观察,发现我们并没有用到树的性质。考虑树上的消元和 DAG 的消元的本质区别。如果从下往上推的话,只有一项 \(f_{fa_u,s}\) 会干扰朴素的转移,大胆猜测可以直接待定系数法。令 \(f_{u,s}=k_{u,s}f_{fa_u,s}+b_{u,s}\),经过一些推式子,发现 \(k_{u,s},b_{u,s}\) 只和子结点有关,而且我们只关心 \(k,b\) 的值,因为本题钦定根 \(x\),而显然根的答案就是 \(b\),因为他爸死了。

至此,我们的 dp 部分可以做到线性。总复杂度为 \(O(2^nn+qn)\),可以通过。

CF1305G Kuroni and Antihype

邀请 \(v\) 可以获得 \(a_u\) 的分数,这并不对称,直接连边无法体现出方向性。考虑一个转换,我们强制让边权对称,连边 \((u,v,a_u+a_v)\),最后算完最大生成森林之后减去 \(\sum a_i\) 就是答案。问题转换成与运算完全图的最大生成森林。考虑建虚点 \(a_{n+1}=0\) 变成最大生成树。注意到两个点之间有关当且仅当 \(a_i\& a_j=0\),这等价于二进制位不交,因此我们将 \(a_i+a_j\) 刻画为 \(a_i|a_j\)。考虑模拟 kruskal 的过程,从大到小枚举每个二进制数 \(s\),枚举 \(s\) 的子集 \(t\),并考虑 \(a_i=t,a_j=s\oplus t\) 这种边,用一个桶维护 \(a_i\) 的出现次数,dsu 合并即可。复杂度 \(O(3^{\log n})\)

还有一种做法是 B 算法,考虑连通块的最大出边,不难发现这其实是一个子集最大值状物,FWT 即可。

P2934 [USACO09JAN] Safe Travel G

由于最短路唯一,我们考虑将所有在最短路上的边形成的子图建出来,每次松弛的时候连接两点即可。不难发现这会形成一棵树,即最短路树。ban 掉最短路最后一条边等价于我们需要从根 \(1\) 走到 \(i\),但不能走边 \((fa_i,i)\),也就是我们需要通过非树边绕上去。显然我们最终只会用一条非树边,令其为 \((u,v,w)\)

考虑这条非树边什么时候可能对 \(i\) 的答案造成贡献,发现当且仅当 \(u\)\(v\)\(i\) 子树中点、且 \(\text{lca}(u,v)\)\(i\) 祖先时,其贡献为 \(dis_u+dis_v+w-dis_i\)。将 \(dis_u+dis_v+w\) 打包成一个权值后按这个权值从小到大排序,按序用每条非树边去更新能更新的 \(i\) 的答案。反过来考虑对于 \((u,v,w)\),哪些 \(i\) 可能被更新,即 \((u,v)\) 路径上除了 \(\text{lca}\) 之外的点。可以树剖路径覆盖,也可以暴力跳路径更新,由于每个 \(i\) 只有第一次被更新是最优的,因此更新完 \(i\) 之后并查集把 \(i\) 缩掉即可。复杂度 \(O(m\log m)\)

CF2133E I Yearned For The Mines

考虑一条链怎么构造,只需要按从左到右扫一遍即可。也就是说如果我们通过 \(2\) 操作将树删成了若干条链的话,我们就可以通过 \(n\) 次操作把所有链扫完。问题转换成如何在 \(\frac{n}{4}\) 次操作将树删成若干条链。我们自下而上 dfs,若当前子树大小 \(\ge 4\),直接对这个点做操作 \(2\),随后将这个点的 \(sz\) 置为 \(0\)。由于子树大小 \(\le 3\) 时显然满足要求,这样可以归纳的保证划分出的都是链,且由于我们只对所有 \(sz\ge 4\) 的位置操作,因此同样易证至多操作 \(\frac{n}{4}\) 次。于是标记一下每条边是否被删,最终 dfs 构造每条链即可。

P5100 [JOI 2017 Final] 足球 / Soccer

一堆人踢着球向前跑什么的还是太难做了,我们只考虑球的运动。不难发现球在某一时刻只会有三种状态:在地上被人踢着、在天上横着飞、在天上竖着飞,这里拆出横竖是因为每次踢只能朝一个方向。于是可以根据这三种状态建出一个分层图,跑最短路即可。考虑如何建模,首先对于地上的状态,直接让相邻的坐标连 \(C\) 的边权即可;对于横飞状态,两个横着之间连 \(A\) 的边权;对于竖飞状态,两个竖着的之间连 \(A\) 的边权;对于每个坐标,让地上状态向两个飞状态连 \(B\) 的边权,代表从这个天踢上去的费用前置。

发现比较难处理每个坐标从天上到地上的边权,但由于每个人在地上跑消耗的代价一样,我们 bfs 出离每个坐标最近的人的曼哈顿距离,然后乘以 \(C\) 即可,代表这个球从天上落下来之后被最近的那个人「瞬移」控球。复杂度 \(O(nm\log(nm))\)

P10652 [ROI 2017] 前往大都会 (Day 1)

第一问直接做就行了,考虑第二问。要走在最短路上的限制不太好处理,可以建出最短路 DAG,这样每一条 DAG 上的路径就对应了一条最短路,我们在 DAG 上 dp 即可。令 \(f_u\) 代表走到了 \(u\) 的最大收益,显然有转移 \(f_u=\max(f_v +(dis_u-dis_v)^2)\),其中需要保证 \(u\)\(v\) 在同一条轨道上且在 DAG 上连通。这个转移显然可以斜率优化,但无法处理哪些 \(v\) 能对 \(u\) 造成转移。

注意到每条轨道一定被最短路 DAG 「划分」成了若干段,则每段内的点是可以互相转移的,考虑扫一遍所有轨道,将所有段求出来,并重新标号,保证处于同一段的点的编号相同。随后我们开编号个数棵李超树,按照最短路松弛顺序在 DAG 上转移,每次将 \(u\) 的所有编号放在其李超树上更新。剩下的就是基本的李超树优化 dp 板子了。

CF1361E James and the Chase

求出所有好点什么的还是太难了,先考虑求出一个好点。发现本题有个非常神秘的「好点数量 \(\le 20\%\) 输出 \(-1\)」于是大胆随机化,随机 \(100\) 次点并在一个优秀的复杂度内判断这个点是不是好点,不难发现发现在 \(100\) 次内没找出来好点的概率为 \((\frac{4}{5})^{100}\),趋近于 \(0\) 了。考虑如何 \(O(n)\) 判断一个点是不是好点,我们求出以这个点为根的一棵 dfs 树,则如果出现横叉边或前向边显然无解。

接下来考虑如何求出所有的好点。题目中有保证该图为强连通图,这说明对于 dfs 树上的任意结点 \(u\),存在一条从 \(u\) 子树内穿到 \(fa_u\) 祖链上的反祖边,要不然就不强连通了。且这样的反祖边只会有一条,要不然 \(u\) 子树内有不止一种方案到 \(fa_u\) 了。令 \(u\) 子树内穿上去的唯一一条反祖边连向 \(v\),则 \(u\) 是好点的条件是 \(v\) 也是好点,证明是容易的,只需要正反各推一遍即可。因此,对于一条反祖边,我们直接对其进行树上差分路径覆盖,最后 dfs 自上而下递推出所有的好点即可。复杂度 \(O(n)\),因为覆盖的是反祖边。

posted @ 2025-08-31 00:07  NagasakiSoyo  阅读(9)  评论(0)    收藏  举报