XCPC 训练题乱做
ECFinal2023 C. Equal Sums
记值域为 \(w\) 并认为 \(n,m\) 同阶,直接背包的话和的值域能够达到 \(O(nw)\),统计每个答案的复杂度也是 \(O(nw)\),于是总复杂度是 \(O(n^3w)\)。
注意到最后需要维护的信息仅仅是 \(\sum x_i = \sum y_j \Leftrightarrow \sum x_i - \sum y_j = 0\),记这个差为 \(d\),我们实际上能够通过调整两侧加入的顺序来将 \(d\) 控制在 \([-w,w]\)。
具体而言,考虑若有 \(\sum_{i=1}^a x_i - \sum_{j=1}^b y_j = 0\),可以按如下算法构造一条从 \((0,0)\) 到 \((a,b)\) 的路径:
-
设变量 \(i=0,j=0\) 表示当前位置,\(d=0\) 表示两侧和之差。
-
若 \(d \leq 0\),令 \(d \leftarrow d+x_{i+1}, i \leftarrow i+1\).
-
若 \(d > 0\),令 \(d \leftarrow d-y_{j+1}, j \leftarrow j+1\).
-
当 \(i=a, j=b\) 时停止。可以发现 \(i=a\) 时 \(i\) 不会再增加,\(j=b\) 时 \(j\) 不会再增加,故一定能够停止。
-
由此构造出三元组序列 \(P=\{i_t,j_t,d_t\}\).
可以发现一个合法的 \(P\) 一定对应唯一的 \((\{x_i\},\{y_i\})\),故其构成双射。
整个过程中 \(d\) 都被控制在 \([-w,w]\) 内,于是设 \(dp_{i,j,d}\) 表示上述算法进行到状态 \((i,j,d)\) 的方案数,用一点前缀和优化转移。时间复杂度 \(O(nmw)\).
ECFinal2023 I. Balance
考虑 \(x=\text{argmin}\{a_i\}, y=\text{argmax}\{a_i\}\),拉出 \(x \leadsto y\) 的任意一条路径 \((d_1=x,d_2,\cdots,d_k=y)\),然后:
这跟题目给出的不等号方向相反,所以所有不等号都必须取等,也就是说:
-
路径上点权递增,即 \(\forall t \in [1,k), a_{d_i} < a_{d_{t+1}}\).
-
除了路径的其他边的两个端点权值必须相等,即 \(\forall (u,v) \notin E(\text{path}), a_u=a_v\).
-
推论:任意一个点的点权必须在路径上出现过,即 \(\forall u \in V, \exist x \in V(\text{path}), a_u=a_x\).
于是将所有出现的点权排序并记 \(c_i\) 表示第 \(t\) 大点权有多少个点。枚举 \(x \leadsto y\) 的路径的 LCA,分别考虑 LCA 的前后路径。以前面的路径为例,记第 \(t\) 大点权深度最浅的点是 \(b_i\),那么必须有 \(siz_{b_i} = \sum_{j=1}^t c_j\) 且 \(b_i \in subtree_{b_{t+1}}\).
注意到对于一个点 \(u\),满足 \(siz_u = \sum_{j=1}^t c_j\) 的 \(t\) 至多只有一个,记为 \(f_u\)(若不存在则为 \(0\))。直接转移即:
DP 完枚举 LCA 统计即可,一车细节。时间复杂度 \(O(n)\).
ECFinal 2022 A. Coloring
称颜色为 \(1\) 的点为黑点,为 \(0\) 的点为白点。
首先连边 \((a_i,i)\),由于每个点入度均为 \(1\),图一定是外向基环树(只关心 \(s\) 所在的连通块,可能有自环)。
先只考虑环上,容易发现任意时刻环上黑点一定形成一个区间 \([l,r]\),并且它们可以不断向右移动。枚举最后 \(l,r\) 的值以及转了几圈,就可以确定每个点变化了多少次(以及最后的颜色)。
再考虑每棵子树,环上点颜色变化的次数决定了一条链上黑白交替的最大次数。设 \(f_{u,t},g_{u,t}\) 表示黑白交替了变化 \(t\) 轮且最后是黑点/白点的最大贡献,树上 DP 即可。
枚举 \(l,r\) 可以用前缀和优化,一百车细节。时间复杂度 \(O(n^2)\).
ECFinal 2022 B. Binary String
这不是我出的题吗
不过其实环上的问题不需要转换成序列做。找到上面提到的循环移位,然后按转化后的操作容易维护某时刻所有 \(R\) 的位置(虽然这题并不需要)。
这题里扫一遍求出 \(R\) 什么时候停止移动,然后跑 KMP 算出最小周期即可。复杂度 \(O(n)\).
ECFinal 2021 C. String-dle Count
所有信息可以转化为四种限制:
-
位置 \(p\) 上必须填字母 \(c\)。
-
位置 \(p\) 上不能填字母 \(c\)。
-
字母 \(c\) 出现了恰好 \(t\) 次。
-
字母 \(c\) 出现了至少 \(t\) 次。
直接子集卷积是 \(O(|\Sigma| k^2 2^k)\),无法通过。
利用一些性质,记字母 \(c\) 出现次数的下限为 \(f_c\),那么必须有 \(\sum_c f_c \leq k\),否则必然无解。
一个神奇的 trick:记 \(dp_{i,state}\) 表示填前 \(i\) 个位置,状态为 \(state\) 的方案数。\(state\) 记录每种字符 \(c\) 填了超过 \(f_c\) 个 / 未超过 \(f_c\) 个且具体填了几个。
实现时可以新建一个序列,填入 \(f_c\) 个字符 \(c\),然后直接用二进制数状压 \(state\)。总时间复杂度 \(O(|\Sigma| k 2^k)\).
Ptz2024 Day3 C. Yet Another Shortest Path Query
平面图 Trick 题。
平面图满足性质 \(m \leq 3n-6\),由抽屉原理可得至少有一个点度数不超过 \(5\)。于是不停地删去度数 \(\leq 5\) 的点,得到每个点被删去的时间戳 \(p_u\)。
考虑将每条边 \((u,v)\) 看作两条有向边 \(u \to v\), \(v \to u\):
-
若 \(p_u > p_v\),记该边为 R 型边。每个 \(u\) 至多只有 \(5\) 条 R 型出边。
-
若 \(p_v < p_u\),记该边为 L 型边。每个 \(v\) 至多只有 \(5\) 条 L 型入边。
接下来考虑可能的路径类型,先考虑 \(len=3\),记 X 表示 L 或 R:
-
RXX
:枚举 \(s\) 的 R 型出边,转化为 \(5\) 个 \(len=2\) 的子问题。 -
XXL
:枚举 \(t\) 的 L 型入边,转化为 \(5\) 个 \(len=2\) 的子问题。 -
LRR
:按 \(s\) 离线,枚举 \(s\) 的所有 L 型出边再枚举两层 R 型出边,\(25\) 次枚举. -
LLR
:按 \(t\) 离线,枚举 \(t\) 的所有 R 型入边再枚举两层 L 型入边,\(25\) 次枚举.
LRR
与 LLR
的复杂度大约为 \(O(50m)\),同时产生了至多 \(10q\) 个 \(len=2\) 子问题。
对于 \(len=2\),同样:
-
RX
:枚举 \(s\) 的 R 型出边,转化为 \(5\) 个 \(len=1\) 的子问题。 -
XL
:枚举 \(t\) 的 L 型入边,转化为 \(5\) 个 \(len=1\) 的子问题。 -
LR
:按 \(s\) 离线,枚举 \(s\) 的所有 L 型出边再枚举一层 R 型出边,\(5\) 次枚举.
LR
的复杂度大约为 \(O(10q+m) \cdot 5 = O(50q+5m)\),同时产生了至多 \(100q\) 个 \(len=1\) 子问题。
对于 \(len=1\),直接枚举 \(s\) 的 R 型出边和 \(t\) 的 L 型入边。这里的复杂度大约为 \(O(1000q)\).
于是总复杂度上界大概是 \(O(1000q+50m)\)。注意实现时 \(len=1\) 的子问题可以直接计算,不需要存下来。
Ptz2024 Day3 I. Dreamy Putata
列出方程,发现每一层可以由上面两层递推而来。假设不考虑 \((tx,ty)\) 处方程的特殊性,直接以前两层 \(2m\) 个点为主元,用线段树维护矩阵乘法计算转移矩阵,最后再以第一行和最后一行导出的方程组高斯消元即可。
但是 \((tx,ty)\) 处方程不一样,为 \(f_{tx,ty}=0\),所以 \(f_{tx+1,ty}\) 实际上是没有办法用前两层的主元推出的。所以设 \(f_{tx+1,ty}\) 为一个新的主元,同时由于 \(f_{tx+1,ty}\) 可以用前两层主元表示,新增了一个方程组,故最后得到的方程组数量和主元数量还是一致的。
注意上述做法有一车特殊情况,比如 \(tx=0\)(新主元和原主元会重复),\(tx=n-1\)(没有新主元,第一行少导出一个方程组)。以及由于 \(tx\) 前后转移不一样,需要分段算;以及方程里的常数项导致需要新开一个矩阵乘法线段树。
总时间复杂度 \(O(q (2m)^3 \log n)\).
CCPC Final 2023 B. Periodic Sequence
首先找上界。有一个显然的结论:对于任意一个可能出现的字符串 \(S_i\),一定存在 \(k \leq |S_1|\) 使得 \(S_i = S_1[1:k] + S_1[1:i_1] + \cdots + S_1[1:i_t]\),其中 \(1 \leq i_1, i_2, \cdots, i_t \leq k\)。容易归纳证明。
所以上界显然就是令 \(S_1 = \text{'a'}+\text{'b'} \times (n-1)\) 时,所有这样的序列的个数,下面证明存在一个字符串序列能将它们全部串起来。
从 \(n\) 到 \(1\) 枚举 \(k\)。对于某个 \(k\),把所有字符串连成一棵树,\(S_i = S_1[1:k] + S_1[1:i_1] + \cdots + S_1[1:i_t]\) 即看作依次走边 \(i_1,i_2,\cdots,i_t\) 到达的点。显然所有深度不超过 \(l-k\) 的点与所有可能的字符串一一对应。
那么假设现在字符串序列的末尾对应的节点是 \(u\),添加一个新的串在树上对应:
-
对于所有 \(u\) 的儿子 \(v\),可以走到 \(v\)(对应新增一个前缀)。
-
对于所有 \(u\) 的祖先 \(x\),若 \(y\) 是 \(x\) 的某个更小的兄弟,则可以走到 \(x\) 或 \(y\)(对应删去一个后缀)。
-
可能可以走到比儿子更深的节点,但此证明中不考虑。
按深度归纳证明如果初始时在根节点,那么可以遍历树上所有节点(并在某个节点停止)。假设根节点的儿子(按边权从小到大)依次为 \(s_1,s_2,\cdots,s_k\),且 \(s_i\) 子树下按归纳假设构造的路径停止在 \(t_i\) 节点,那么直接按照以下方式构造:
最后,对于不同的 \(k\),也可以类似上面的路径从大到小把根串起来。于是证明了存在一个字符串序列能将它们全部串起来,即上限能达到。
接下来考虑计数,枚举 \(k\),则有:
一种暴力做法是对于某个 \(k\),转成线性递推,可以 \(O(n)\) 算出所有系数。
另一种做法是暴力拆开:
注意这里出现了 \(kr\),于是考虑根号分治。对于 \(k < B\),用前面提到的暴力做法;对于 \(k \geq B\),一定有 \(r \leq \lfloor n/B \rfloor \triangleq B_0\),然后枚举 \(r\):
令 \(B = O(\sqrt n)\),时间复杂度 \(O(n \sqrt n)\)。
CCPC Final 2023 K. Sticks
场上推出来结论,调了半天发现好像假了,换了个容斥做法赛后又调了一晚上。结果在写这篇题解的时候突然发现场上做法没假,改了三行过了...
设左侧第 \(i\) 行的棍子长度为 \(x_i\),上方第 \(j\) 列的棍子长度为 \(y_j\)。
定义:对于一种摆放方式,若 \(\forall i \in [1,n], y_{x_i+1} \neq i\),称其该摆放方式合法,即不存在以下形状:
...|
...|
-->∨
Lemma 1. 任意一个可能达到的矩阵 \(A\) 都存在至少一种合法摆放方式。
Proof 1. 对于 \(A\) 的任意一种摆放方式,找到最小的 \(x_i\) 使得 \(y_{x_i+1} = i\) 并令 \(y_{x_i+1} \leftarrow y_{x_i+1}-1, x_i \leftarrow x_i+1\)。调整后冲突的最小 \(x_i\) 至少增加 \(1\),故有限次调整后能找到一种合法摆放方式。
Lemma 2. 任意零一矩阵 \(A\) 至多只有一种合法摆放方式。
Proof 2. 枚举 \(k=n,n-1,\cdots,1\),不断执行以下流程:
- 求出 \(t \in [0,k]\) 满足 \(A_{k,1}=A_{k,2}=\cdots=A_{k,t}=1, A_{k,t+1}=0\). 那么必然有 \(y_k=t\),且若 \(s>t, A_{k,s}=1\) 则有 \(x_s = k\) 并删去第 \(s\) 行(若不全为 \(1\) 则终止)。
该流程要么提前终止,要么给出唯一的合法摆放方式并且没有其他可能。
Collary. 所有可能达到的矩阵 \(A\) 与合法摆放方式构成双射。
于是现在问题变为了计数满足 \(\forall i \in [1,n], y_{x_i+1} \neq i\) 的 \((\{x_i\},\{y_i\})\) 序列数量。
设 \(dp_{i,j}\) 表示考虑前 \(i\) 列且 \(\max_{t=1}^i \{y_t\}=j\)。转移考虑分成
-
若 \(y_{i+1} \leq j\),则转移为 \(dp_{i,j} \to dp_{i+1,j}\),系数直接乘上方案数即可。
-
若 \(y_{i+1} > j\),则转移为 \(dp_{i,j} \to dp_{i+1,k} (k>j)\),相当于要求 \(x_{j+1}, x_{j+2}, \cdots, x_{k-1} \leq i\) 且 \(x_k < i\),分步转移即可。
总时间复杂度 \(O(n^2)\)。
CCPC Final 2023 M. Bot Friends
[注:暂时无法确认本篇题解完全正确]
首先注意到没有 bot 能到达 \(0\) 或 \(n+2\) 位置(容易反证),也就是说 bot 只能到达 \(n+1\) 个坑,那么必然恰有一个坑最后是空的。
同理,只考虑区间 \([l,r]\) 内的 bot,如果最后空出来的坑在最左边,称这个区间为 R 型块;如果最后空出来的坑在最右边,称这个区间为 L 型块。那么考虑整个过程,依次考虑每一步:
-
每一步中,如果移动的机器人向右并且它右边紧挨着一个 L 型块,那么它与 L 型块合并成一个新的 R 型块并重复这个过程;否则它自己成为一个新的 R 型块。
-
如果移动的机器人向左并且它左边紧挨着一个 R 型块,那么它与 R 型块合并成一个新的 L 型块并重复这个过程;否则它自己成为一个新的 L 型块。
所以整个过程始终只有未操作的 bot,L 型块与 R 型块。那么最后的局面一定是左边若干 L 型块 + 右边若干 R 型块。问题就是最小化未能合并(自己成为一个新块)的 bot 数量。
同时注意到如果在合并过程中建边,会形成一棵类似表达式树的结构,如:
-
R 型块 = '>' + (L型块)*;或者 R 型块 = '>'(花费 \(1\) 代价)
-
L 型块 = (R型块)* + '<';或者 L 型块 = '<'(花费 \(1\) 代价)
分析到这里已经可以区间 DP,记 \(f_{l,r},g_{l,r}\) 分别表示 \([l,r]\) 为 L 型块与 R 型块时的最小代价。时间复杂度 \(O(n^3)\)。
既然是表达式树,就可能可以通过从左到右扫描并维护栈来描述它。先只考虑最后全为 L 型块的情况(即最后状态的一个前缀),可以将 >
类似看作左括号并将 <
类似看作右括号,有如下规则:
-
遇到
>
:在栈上插入一个>
;如果下一个 bot 立刻将它删去,则会产生 \(1\) 的代价(对应 R 型块 = '>')。 -
遇到
<
:弹栈一次;或者花费 \(1\) 代价不删除(对应 L 型块 = '<')。
于是直接记 \(dp_{i,j,0/1}\) 表示处理到第 \(i\) 个 bot,栈内有 \(j\) 个 >
,第 \(i\) 个 bot 是否是 >
的最小代价,容易转移。
最后对左右各做一次,枚举最后状态的坑位置合并即可。时间复杂度 \(O(n^2)\)。
ECFinal 2019 B. Black and White
经过多番尝试之后,一步一步考虑基本上不可能很好地挖掘性质。一个好的想法是两步两步考虑。
首先对于考虑 \(2 \nmid n+m\) 的情况,可以枚举第一步来转化为 \(2 \mid n+m\)。
那么现在 \(n+m\) 步被划分为了 \((n+m)/2\) 组。记向上走为 A,向右走为 B,考虑两种贡献计算方式:
- 向右走时不计算贡献,向上走时计算左侧的贡献。容易发现 AA 和 BB 始终不产生贡献,而剩下两种:
(x mod 2, y mod 2) | BA | AB |
---|---|---|
\((0,0)\) | \(1\) | \(0\) |
\((1,1)\) | \(0\) | \(-1\) |
- 向上走时不计算贡献,向右走时计算上方的贡献。这时贡献的计算与 \(n\) 奇偶性有关:
(x mod 2, y mod 2) | BA(2 | n) | AB (2 | n) | BA (2 ∤ n) | AB (2 ∤ n) |
---|---|---|---|---|
\((0,0)\) | \(0\) | \(-1\) | \(1\) | \(0\) |
\((1,1)\) | \(1\) | \(0\) | \(0\) | \(-1\) |
看起来没有规律很难处理,但是如果我们把两种计算方式加起来(算两次),就会发生神奇的事情:
(x mod 2, y mod 2) | BA(2 | n) | AB (2 | n) | BA (2 ∤ n) | AB (2 ∤ n) |
---|---|---|---|---|
\((0,0)\) | \(1\) | \(-1\) | \(2\) | \(0\) |
\((1,1)\) | \(1\) | \(-1\) | \(0\) | \(-2\) |
- 先考虑 \(2 \mid n,m\),此时贡献已经跟位置没有关系了,直接枚举 BA 填了 \(t\) 个,AB 填了 \(t-k\) 个,可以算出 AA 和 BB 的数量,然后直接可重排:
- 对于 \(2 \nmid n,m\),注意到如果给每个 \((0,0)\) 减一,给每个 \((1,1)\) 加一,就可以归到前一种情况。而 \((0,0)\) 一定比 \((1,1)\) 多一,因此先把 \(k\) 减一再照前一种情况做即可。
时间复杂度 \(O(T\min\{n,m\})\).
CCPC2024 Harbin H. Subsequence Counting
首先把逆变换变成正的。求出 \(k\) 在模 \(L\) 意义下的逆元 \(d\),则 \(s'_i = s_{id \bmod k}\).
注意到 \(m\) 很小,这启发我们可以把 DP 写成矩阵形式,每个矩阵大小是 \(m+1\). 那么问题变成:现有 \(n\) 段 \(L\) 个矩阵,求它们在经过变换重排后的乘积。如果记原本的矩阵序列为 \(s_0,s_1,\cdots,s_{L-1}\),那么就是要求(以下均省略下标的模 \(L\)):
记这个问题为 \(f(L,d,n)\),神奇的是,这竟然可以用类似欧几里德的方法进行递归。
考虑将原本序列每隔 \(d\) 个就换一次行,类似:
那么,要求的矩阵乘积就变成了:从左到右对每一列求乘积,再按照跳跃顺序将这些列的乘积相乘。跳跃的顺序为:\(0, d-(L \bmod d), 2[d-(L \bmod d)], \cdots\).
而由于原本只有 \(n\) 段矩阵,所以乘积不一样的列只有至多 \(n+1\) 个,并且可以在找出所有断点后用线段树维护。于是可以获得每一列的乘积。
这样就变成了一个子问题 \(f(d, d-(L \bmod d), n+1)\),可以递归下去。
这里有一个小问题:如果 \(d\) 很接近 \(L\),那么递归的子问题规模并没有减少太多。不过注意到此时我们可以令 \(d\) 变成 \(L-d\),即:
也即把 \(s_0\) 后面的矩阵顺序翻转。这很容易实现,并且至多只会让段数增加 \(1\).
于是这样,每两次递归后 \(d\) 至少会减半,递归深度至多 \(O(\log L)\),并且矩阵增加的端数也是至多 \(O(\log L)\)。每次递归时需要用线段树维护区间乘矩阵,总复杂度是 \(O(m^3 n \log n \log L)\).
CCPC2023 Shenzhen B. Excuse
每个 \(a_i\) 都服从几何分布,并且 \(P[a_i=k] = 2^{-k-1}\).
首先拆期望 \(E[X]=\sum_{k \geq 1} P[X \geq k]\),而 \(\text{mex} \geq k\) 就是 \(0,1,\cdots,k-1\) 都出现过。记 \(X \geq k\) 的概率为 \(s_k\).
“都出现过”的限制很容易让人想到容斥,但是尝试之后根本没法做。我们尝试用更根本和暴力的办法:直接写成指数型生成函数。
注意到连乘号里面对于不同的 \(k\) 相当于求前缀积,这引发一个大胆的想法:尝试直接求出这个无限乘积,尽管现在我们无法确信它一定收敛。
但是注意到里面每一项都没有常数项,所以至少先对每一项提出 \(x\),得到:
直接取对数。先求出 \(H(x) = \ln \frac{e^x-1}{x}\) 的泰勒展开。展开形式和伯努利数有些联系,不过这里可以直接求多项式的 \(\ln\)。 接下来:
所以 \(G(x)\) 确实是收敛的,直接对上式求多项式 \(\exp\) 即可得到 \(G(x)\) 的多项式展开。
最后,计算答案:
设 \(P(x) = e^x / G(x)\),\(Q(x) = \sum\limits_{k \geq 1} \dfrac{x^k}{2^{k(k+1)/2}} P(x/2^k)\),则:
设 \(d=t-k\),用 Bluestein Method:
于是直接一次卷积即可获得所有 \(Ans_n\) 的值。时间复杂度 \(O(n \log n)\).
Jilin 2023 H. Games on the Ads 2: Painting
显然每个格子都会恰好被行染一次,被列染一次。讨论一下情况:
- 如果 \(c_{i,j} \neq p_i, c_{i,j} \neq q_j\),那么整个无解。
- 如果 \(p_i = q_j\),那么无论怎么染这个格子都合法。
- 否则如果 \(c_{i,j} = p_i\),那么必须先染列再染行;反之亦然。
于是问题转化为给定一个 \(n + n\) 的二分图,且每个点度数均为 \(n-1\),求拓扑排序数量。
少了 \(n\) 条边让人很苦恼,直接大力枚举 \(2^n\) 种给边定向,这样就变成了完全二分图。
这意味着如果确定了列的染色顺序,每个行插入的位置是固定的。
设 \(S_i\) 表示行 \(i\) 被连向的点的集合(即必须在它之前染的列号)。将所有 \(S_i\) 按照集合大小排序,设为 \(S_{i_1}, S_{i_2}, \cdots, S_{i_n}\)。
- 如果存在 \(S_{i_t} \not\subseteq S_{i_{t+1}}\),那么无解。
- 否则,设大小为 \(k\) 的集合有 \(c_k\) 个,那么方案数为 \(\prod_{k=1}^n c_k!\)。
时间复杂度 \(O(n 2^n)\).
Zhejiang 2024 K. Sugar Sweet 3
首先,这就是摩尔投票法,因此最后的局面只由 \(A,B,C\) 决定。最后牌堆里没有牌当且仅当 \(2 \mid A+B+C\) 且 \(2 \max\{A,B,C\} \leq A+B+C\)。
考虑按每次牌堆清空的节点将整个过程分成若干段。称每一段内第一次操作的颜色为该段的主色,那么该段内主色和非主色构成了一个括号序列。这就是整个问题的结构。
对于三种牌数量的限制 \(A,B,C\),可以枚举每种颜色作为主色的数量 \(a,b,c\),然后设每种主色对应的段中,非主色数量的分配具体为:
注意到由于 \(a+b+c=A+B+C\),故只需要枚举 \(a,b\);但是方程组不满秩,故还需要再枚举 \(i\)。枚举 \((a,b,i)\) 后剩下的 \((j,k)\) 可以直接求出。
接下来,枚举三种主色对应段的数量 \(p,q,r\)。那么以主色 \(1\) 为例,将非主色看成一种颜色,只需要求出将 \(2a\) 个括号分为 \(p\) 段括号序列的方案数 \(f(a,p)\),再乘上 \(\binom{a}{i}\) 即可。最后再乘上 \(\binom{p+q+r}{p,q,r}\) 后求和即得到答案。
先考虑求出 \(f(n,k)\) 的值,就是
可以直接 DP 求出;也可以在每个括号序列后加一个右括号,映射为 \((0,0)\) 走到 \((2n+k,-k)\) 的路径数:
接下来,恰有 \(s\) 段的方案数为:
暴力多项式乘法十分爆炸,不过注意到我们实际上要求的是很多个这样的多项式乘积之和,故可以直接插值,这样就变成了点值乘法。
预先将所有 \(F_a(x)\) 和点值处理出来,然后枚举 \(a,b,i\) 的值并累加点值,最后还原即可。总时间复杂度为 \(O(n^3)\),常数小。
3rdUCup Stage40 D. Fern Market
首先如果不考虑计数,这就是那个广为人知的经典反悔贪心题
CF865D Buy Low Sell High。做法是:
- 维护一个小根堆。从前往后考虑每一天,设价格为 \(p_i\):
- 如果堆内没有比 \(p_i\) 小的元素,则将 \(p_i\) 入堆。
- 否则将堆顶元素 \(x\) 出堆,答案加上 \(p_i - x\),然后将 \(p_i\) 入堆两次。
考虑枚举 \(t\),然后统计 \([t,t+1)\) 被算进的贡献。将 \(\leq t\) 的元素标为 \(0\),将 \(>t\) 的元素标为 \(1\),则共有 \(t\) 个 \(0\) 和 \(n-t\) 个 \(1\)。会发现按照上述策略等价于对这个新的序列进行反悔贪心:
- 如果 \(p_i = 0\),那么无论什么情况最后都会往堆里放入一个 \(0\)。
- 如果 \(p_i = 1\),且栈内有 \(0\),则出栈一个 \(0\) 并入栈两个 \(1\);
- 如果 \(p_i = 1\),且栈内没有 \(0\),则无论什么情况最后都会往堆里放入一个 \(1\)。
也就是说,一定能够取到最大值。考虑贪心:
将 \(0\) 看为向右上走一步,将 \(1\) 看为向右下走一步,但已经在 \(0\) 时遇到 \(1\) 只能水平向右走一步,并将这种情况记作“损失”。那么对于一个序列,其最后的贡献就是 \(1\) 的数量减去“损失”发生的次数。
所有 \(1\) 的数量很好算,就是 \((n-t) \binom{n}{t}\)。
对于“损失”,有结论:如果不管在 \(0\) 时遇到 \(1\) 只能水平向右走一步的限制,直接按照普通 Dyck Path 的规则,则“损失”数量等于最低点高度的相反数。
于是枚举 \(r \leq -1\),统计最低点至少低于 \(r\) 的 Dyck Path 数量,最后求和即可。
最后推出来的答案是一个上指标为 \(n\) 的组合数前缀和。故枚举 \(n\),先预处理组合数前缀和,然后再 \(t\) 统计答案即可。时间复杂度 \(O(k^2)\).