2024.9.25 近期练习
CF1261F Xor-Set
我们把 \(A,B\) 集合分别处理,把其拥有的区间放到字典树上,就会拆成 \(O(n\log V)\) 个区间。
考虑其两两组合,每个区间都是形如前面若干位确定,后面 \(x\) 位任意。
两个区间组合,就是取 \(x\) 更大的那个后面都是任意的,前面的若干位合并起来即可。
但是这样就会有 \(O(n^2\log^2V)\) 个区间,我们还需要排序后去重略显困难。考虑减少无用的区间。
钦定 \(q_a\ge q_b\),合并 \([p_a,p_a+2^{q_a})\) 与 \([p_b,p_b+2^{q_b})\) 时,我们接下来还要合并 \([p_b+2^{q_b},p_b+2^{q_b}+2^{q_{b_2}})\)。
上面 \([p_b,p_b+2^{q_b})\) 到 \([p_b+2^{q_b},p_b+2^{q_b}+2^{q_{b_2}})\) 的过程分两段,一段 \(q_b\) 递增,一段递减,段中不进位。
因为段中不进位(段间进位),前 \(q_a\) 位都不变,所以只有 \(q=0\) 或 \(q=q_a\) 的时候有用。
那么区间的数量只有 \(O(n^2\log V)\) 了。
AGC009E Eternal Average
将求平均数的过程看做是一个每个节点儿子数都是 \(k\) 的树,第 \(d\) 层的所有数的贡献是 \(k^{-d}\)。
考虑 \(0,1\) 的深度序列 \(\{x_i\},\{y_i\}\),长度分别为 \(n,m\)。其合法的话就是要其能对应到一棵树上。
将 \(0\) 看做 \(1\),条件很明显也就是只需要满足 \(\sum k^{-x_i}+\sum k^{-y_i}=1\) 即可。
我们也就是要求的是:所有合法 \(x,y\) 序列中 \(\sum k^{-x_i}\) 有多少种,我们不难想到把这个东西写成 \(k\) 进制。
相当于直接 dp 答案的值,也就是说求序列 \(\{z_i\}\) 的个数,使得 \(\sum k^{-x_i}=\sum z_ik^{-i}\)。
假设已知 \(\{z_i\}\),我们要看能否构造出长度为 \(n\) 的序列 \(\{x_i\}\)。
不妨先令 \(x\) 中 \(i\) 的出现次数为 \(z_i\),\(\sum z_i\) 与 \(n\) 的差值可以用下放一位来补齐,每次可以增加 \(k-1\)。
所以 \(\{z_i\}\) 合法的条件是 \(\sum z_i=n\pmod {k-1}\),且 \(\sum z_i \le n\)。
我们还需要考虑 \(1-\sum z_ik^{-i}\) 能构造出长度为 \(m\) 的序列 \(\{y_i\}\)。
也就是 \(1+\sum (k-z_i-1)\le m,1+\sum (k-z_i-1)=m\pmod{k-1}\)。后者跟上面那个同余式等价。
还有一个条件就是 \(z\) 序列长度为 \(l\),\(z_i\in [0,k),z_{l}\neq 0\)。这个可以用 dp 求出答案。
设 \(f_{i,j}\) 表示当前填到前 \(i\) 位,\(\sum z_i=j\) 的方案数。考虑前缀和优化即可。
CF53E Dead Ends
如果不用 dp,那么我们就容斥加矩阵树定理即可,只需要钦定叶子并从图中删掉,剩下的跑矩阵树。
考虑 dp,一个比较显然的状态设计:设 \(f_{s,t}\) 表示集合 \(s\) 里的点构成树,\(t\) 集合的点为叶子的方案数。
转移的话考虑加叶子。加叶子加在原叶子节点下,那么就删掉原来的叶子;否则就多一个叶子节点。
但是这样会算重,如果有多个叶子,那么就会被不同的顺序都算到。
如何才能防止算重呢?我们发现状压 dp 表示的其实是一个在生成树中不断加边的过程,
也就是说,如果能做到让生成树能且仅能通过一种加边顺序形成,就能算出答案。
所以我们每次加入叶子节点时,都钦定这个点是当前剩下的叶子编号最大的即可。
也就是我们每次“围绕基准点构造一个整体”的时候,定编号最大的叶子为基准点并删掉这个点。
这相当于一种“最小表示法”。dp 的时候要遵循这种规律来转移状态。这题比较基础所以讲的很多。
CF1730F Almost Sorted
我们假设把 \(p_i\) 从小到大插入。假设现在加入 \(x\)。\(x\) 能插入某个位置的条件是其后面所有数 \(\ge x-k\)。
发现用插入的做法做的话状态数过大,可能需要 \(O(n\times k!)\)。
所以我们考虑每次在序列最后填一个数,计算前缀的答案。(更换划分子任务的形式)。
假设我们当前填入 \(x\)。那么对于已经填入的数满足 $\le x+k $,对于未填的数 \(\ge x-k\)。
所以考虑一个合法的状态的性质,假设最小的未填的数为 \(x\),那么最大的已填的数不超过 \(x+k\)。
所以我们可以这么设状态,设 \(f_{x,S}\) 表示最小未填的数是 \(x\),\([x+1,x+k]\) 的填的情况为 \(S\) 的答案。
转移比较容易,这个题通过寻找状态的性质来减少状态数。
CF1699E Three Days Grace
考虑枚举最小值 \(k\),设 \(f_{x,k}\) 表示 \(x\) 分解成 \(\ge k\) 的数最大值最小是多少。此时最大值是 \(\max_x(f_{x,k})\)。
我们如果从小到大枚举 \(k\),发现这不太好转移,所以我们从大到小枚举 \(k\),并更新 \(f_x\)。
如果 \(k+1\) 转移到 \(k\) 的时候 \(f_x\) 发生改变,那么 \(k|x\)。
于是我们将 \(x\) 拆一个 \(k\) 出来,剩下 \(x/k\),相当于子任务,那么 \(f_{x,k}=\min(f_{x,k+1},f_{x/k,k})\)。
每次只有 \(k\) 的倍数的 \(x\) 被更新,复杂度就是调和级数了。
同时因为最大值也是递减的不需要数据结构维护一个桶+指针即可。
P6190 [NOI Online #1 入门组] 魔法
考虑我们一个个 \(k\) 加入,当 \(k=0\) 时,计算出 \(f_{0,i,j}\) 表示当前 \(i\to j\) 的距离。
\(k=1\),那么考虑枚举某条边 \((u,v)\) 使得 \(f_{1,i,j}= \min(f_{0,i,u}-w_{u,v}+f_{0,v,j})\)。
\(k=2\),那么 \(f_{2,i,j}=\min(f_{1,i,u}+f_{1,u,j})\)。这个形式就相当于矩阵乘法。
所以,\(f_{t,i,j}=\min(f_{t-1,i,u}+f_{1,u,j})\),使用矩阵快速幂即可。
至于为何想到这个 dp,我们假设已知最优的 \(1\sim n\) 的路径,使用了 \(k\) 个魔法。
考虑划分子任务,于是我们一段一段划分,每次取出最后一段用了魔法的段,来转移。
如果像平时一条边一条边划分,那么会导致 \(k\) 相同时所有点的答案还需要松弛。
CF1773G Game of Questions
非常牛一个题,首先 \(m\) 很小我们考虑状压,不妨设 \(f_S\) 表示剩余选手为 \(S\) 时 \(1\) 获胜的概率。
考虑 \(S\) 从 \(T\) 转移,其中 \(T\subset S\),考虑取出所有能使得 \(S\) 发生变化的题目,设有 \(k\) 个。
\(S\) 的转移取决于上述题目第一个出现的题,每个题作为第一次出现的概率都是 \(\frac{1}{k}\)。
不妨求 \(g_{S,T}\) 表示能使得 \(S\) 改变到 \(T\) 的题目数量,那么 \(S\) 改变到 \(T\) 的概率是 \(\dfrac{g_{S,T}}{n-g_{S,S}-g_{S,\empty}}\)。
也就是说,所有能使得状态改变的题目都是其对应集合里第一次出现的。
对于非第一次出现的,这个题是没有用的。
对于 \(g\) 的求就比较简单了。\(g_{S,T}=g_{S+x,T} +g_{S+x,T+x}\)。其中 \(x\) 取任意不在 \(S\) 的元素都可以。
ABC134F Permutation Oddness
\(\sum_{i=1}^n|p_i-i|\) 的贡献形式让我们想到可以“在每个空隙计算贡献”。
对于 \(j\to j+1\) 的空隙,当 \(p_i,i\) 分属左右时就会产生 \(1\) 的贡献。
考虑求已经计算了前 \(i\) 个空隙的答案,考虑其状态对后面造成什么影响。
影响因素有:\(i\) 还没有 \(p_i\) 与其配对的有多少个记为 \(x\)、\(p_i\) 没有与 \(i\) 配对的有多少个,记为 \(y\)。
那么第 \(i\to i+1\) 的贡献数就是 \(x+y\)。
关于 \(p_{i+1}\) 的填有两种:一种是填一个还没有填的 \(x\),使 \(x\gets x-1\);或者是不填,使 \(y\gets y+1\)。
此时 \(i+1\) 还可以使以前的未配对的 \(y\) 配对,使 \(y\to y-1\),或者等待后面的 \(p\) 与其配对,\(x\gets x+1\)。
还有一种情况是 \(i\) 直接与 \(p_i\) 配对了。
设 \(x,y\) 你发现非常蠢,因为一定满足 \(x=y\),因为二分图两侧点相同。
于是设状态 \(f_{i,x,now}\) 表示填了前 \(i\) 位,\(x\) 的取值已知,当前贡献是 \(now\) 的方案数。
关于转移:\(x\) 不变的方案数是 \(2x+1\);\(x\gets x+1\) 方案数是 \(1\);\(x\gets x-1\) 的方案数是 \(x^2\)。
复杂度 \(O(n^4)\),转移 \(O(1)\)。
P2523 [HAOI2011] Problem c
考虑转化限制条件。不难发现人的编号是没有意义的,只要存在一个座位没有被坐到就是违法。
不妨从后往前填,设 \(f_{i,j,k}\) 表示当前填了 \(\ge i\) 的人,已经确定 \(j\) 人的 \(a\)、\(k\) 个位置没有填的方案数。
转移的话我们需要枚举当前位置填 \(t\) 个人,除去题目给定 \(a_j=i\) 的人,算组合数为贡献。
不难发现你蠢的一批,\(j,k\) 等价,然后复杂度就是 \(O(n^3)\) 了。
P9131 [USACO23FEB] Problem Setting P
考虑将这个问题模型化。首先每个验题人都必须满足先简单后难的限制,
于是设 \(s\) 表示当前觉得困难的人的集合,不难看出后面的 \(s\) 一定包含前面的 \(s\)。
我们选的题目,设觉得这道题困难人的集合是 \(t\),那么 \(s\subset t\),并令 \(s\gets t\)。
所以相当于我们计数选 \(t\) 序列满足偏序关系的方案数。设 \(f_s\) 表示当前集合为 \(s\) 方案数。
于是对于所有 \(t\) 的子集 \(s\) 都可以转移过来,并令 \(g_t\gets g_t\times s(cnt_t)\),\(cnt_t\) 表示 \(t\) 集合的数量。
\(s(x)\) 表示从 \(x\) 个数任选排列的个数,直接 \(\sum_{i=1}^xA_{x}^i\)。
转移的话是一个动态的过程,求子集和,我们可以 popcount 从小到大每层做高维前缀和。
然而复杂度可以减少一个 \(m\)。
考虑分治,也就是对于每一位,我们先计算 \(0\) 的答案,\(1\) 加上 \(0\) 的答案后再计算。
具体地,只需要类似 FWT 的过程,在分治到第 \(i\) 位的时候维护 \([j,j+2^i)\) 的和即可。
CF1781F Bracket Insertion
一般括号串的问题都是要设区间 Dp,设 \(f_{l,r,0/1}\) 表示 \([l,r]\) 合法,上一次操作是外面套括号/两个拼起来。
这个题的所有操作,如果将顺序倒过来,就相当于再某个区间外面套一个 () 或 )(。
但这个题一个区间不一定满足合法,但是我们可以钦定其是由若干操作构成的,即没有单独的括号。
这里令左括号对应 \(-1\),右括号对应 \(1\),一个区间是合法序列的条件是前缀 \(\max\) 是 \(0\)。
状态容易合并,设 \(f_{l,r,k,0/1}\) 表示区间 \([l,r]\) ,前缀 \(\max\) 是 \(k\) 的方案数,\(0/1\) 对应上一次操作。
因为一个状态里的区间一定满足和为 \(0\),所以 \(k\) 的值是直接取 \(\max\) 即可。
有两种转移,两个区间拼起来的话,\(k\) 取 \(\max\),贡献乘上组合数,即组合操作顺序,可以前缀和优化。
外面套括号,要乘上概率,并令 \(k\) 加上 \(1\) 或减去 \(1\) 即可。
由于 \(f\) 是把所有插入的情况加起来,只算了 \(p\) 的贡献,最后 \(Ans=f_{1,n,0}\times \prod_{i=1}^n\frac{1}{2i-1}\)。
最优注意到所有区间都是等价的,也就是长度相同的答案相同,复杂度 \(O(n^3)\)。
P6563 [SBCOI2020] 一直在你身旁
设 \(f_{l,r}\) 表示当前已经确定电线范围在 \([l,r]\),找到电线长所有情况下的最小花费。
转移的话枚举当前购买哪条电线,设买了第 \(p\) 条,那么 \(f_{l,r}=\min(\max(f_{l,p},f_{p+1,r})+a_p)\)。
然而转移需要 \(O(n)\),复杂度 \(O(n^3)\),尝试优化。
注意到 \(f_{l,p}\) 随着 \(p\) 增大而增大,\(f_{p,r}\) 随 \(p\) 增加而变小,所以有一个分界点,那么 \(\max\) 可以去掉。
考虑固定左端点,求右端点的答案。我们左端点从大到小枚举,并把右端点也从大到小枚举。
那么,分界点也是递增,就好比滑动窗口,用双指针+单调队列即可。

浙公网安备 33010602011771号