SCCPC2025 题目&题解
SCCPC2025 题目&题解
我认为的难度排序:IHFAKJCLEDBG
A. 最小乘积
有一个 \(n\) 个点 \(m\) 条边的有向图,每条边有两个属性 \((a_i,b_i)\),你需要求一条 \(1\) 到 \(n\) 的路径 \(P\),使得以下权值最小。
\[(\sum_{i\in P}a_i)(\sum_{i\in P}b_i) \]多组数据。\(n\le 300,m\le 1000,1\le a_i,b_i\le 200,\sum n\le 1000,\sum m\le 2000\)
最小乘积模型板子。
或者考虑 dp,设 \(f_{u,s}\) 表示走到 \(u\),当 \(\sum a_i=s\) 时,\(\sum b_i\) 最小是多少,那么 \(s\) 的上界为 \(n\times\max\{a_i\}\)。但如果直接像最短路一样转移会多 \(\log\)。
注意到 \(a_i > 0\),所以对于一个 \(s\),所有 \(f_{u,s}\) 之间没有连边,不会互相转移。于是可以从小到大枚举 \(s\),然后再枚举每条边做转移 \(f_{v,s+a}\larr f_{u,s}+b\)。时间复杂度为 \(\mathcal{O}(nm\max\{a_i\})\)。
B. 三进制
交互题。
现在有一种对 \(n\) 位三进制数的加密方法,对每一位 \(i\) 构造一个双射 \(f_i:\{0,1,2\}\to\{0,1,2\}\),那么一个 \(n\) 位三进制数 A 加密后为:
\[f_{n-1}(a_{n-1})f_{n-2}(a_{n-2})\ldots f_0(a_0) \]现在你可以询问两次加密状态下的加法结果,你需要求出 \(f_0\ldots f_{n-1}\) 分别是什么。
具体的,你每次询问应该给出两个 \(n\) 位的三进制数 \(a,b\),设 \(f^{-1}\) 表示 \(f\) 的逆运算,即解密操作,那么交互库会返回一个 \(n+1\) 位三进制数表示 \(f(f^{-1}(a)+f^{-1}(b))\)。注意最高位不会加密。
多组数据。\(n\le 10^5,\sum n\le 10^6\)
对于第一次询问,我们考虑问 \(n\) 个 \(0\) 和 \(n\) 个 \(1\)。然后从低到高扫每一位,并记录上一位是否有进位,初始时没有进位,对于每一位:
-
上一位没有进位:
- 这一位的结果是 \(2\),那么说明 \(0,1\) 对应了 \(1,2\),\(2\) 一定对应 \(0\),并且这一位发生进位。
- 这一位的结果是 \(0\) 或 \(1\),那么这一位的结果取反的数一定对应 \(0\),并且这一位不发生进位。
此时一定可以确定出哪个数对应 \(0\)。
-
上一位有进位:
- 这一位的结果是 \(2\),那么说明 \(0,1\) 对应了 \(0,1\),\(2\) 一定对应 \(2\),并且这一位不发生进位。
- 这一位的结果是 \(0\) 或 \(1\),那么这一位的结果取反的数一定对应 \(2\),并且这一位发生进位。
此时一定可以确定出哪个数对应 \(2\)。
于是对于每个位置,我们都可以确定出其中一个对应关系。
接下来第二个询问,我们对于每一位,因为剩下两个没确定的数是等价的,所以任选一个数 \(x\),在 \(a\) 和 \(b\) 的这一位都填上 \(x\)。然后我们从高到低扫每一位,并记录这一位是否该发生进位,初始时根据最高位是否为 \(1\) 来判断,对于每一位:
- 这一位已经确定了哪个数对应 \(0\),不妨设 \(0\) 对应 \(0\),我们询问的是两个 \(1\),现在要求 \(1\) 对应哪个数:
- 这一位结果为 \(0\),那么 \(1\) 对应 \(1\),并且下一位应该有进位。
- 这一位结果为 \(1\),那么 \(1\) 对应 \(2\),并且下一位应该有进位。
- 这一位结果为 \(2\),那么下一位不应该有进位。如果这一位应该有进位,那么 \(1\) 对应 \(2\),否则 \(1\) 对应 \(1\)。
- 这一位已经确定了哪个数对应 \(2\),不妨设 \(2\) 对应 \(2\),我们询问的是两个 \(1\),现在要求 \(1\) 对应哪个数:
- 这一位结果为 \(0\),那么下一位应该有进位。如果这一位应该有进位,那么 \(1\) 对应 \(1\),否则,\(1\) 对应 \(0\)。
- 这一位结果为 \(1\),那么 \(1\) 对应 \(0\),并且下一位不应该有进位。
- 这一位结果为 \(2\),那么 \(1\) 对应 \(1\),并且下一位不应该有进位。
于是每一位都可以确定 \(f_i\) 是什么了。复杂度线性。
C. 最优时间
给定 \(n\),定义 \(S(x)\) 为所有 \(x\) 的因数和不超过 \(n\) 的倍数构成的集合。初始时你有一个 \(x\),每一秒,你有如下两种选择:
- 等概率变成 \(S(x)\) 中的一个数字
- 什么都不做
每秒结束后,\(x\larr x-1\)。求在最有决策下 \(x\) 变为 \(0\) 的期望时间。现在有 \(q\) 次询问,每次给定 \(x\),你需要回答答案。
\(n,q\le 10^5\)
设 \(f_x\) 表示初始为 \(x\) 的答案,则有:
边界为 \(f_0 = 0\)。但这个方程有环,而高斯消元复杂度不能接受。
所以考虑迭代,初始时 \(f_i = i\),然后每一轮对每个 \(x\),记上一轮的答案为 \(g\),进行:
然后迭代 \(100\) 轮即可。或者可以用 SPFA 优化,直到的所有更新的改变不超过 eps 即可。
D. 三分图
一张无向图是三分图,当且仅当存在一种给每个点染上 \(1,2,3\) 中的一个颜色的方案,使得每条边连接的两个点颜色不同。
对于一个 \(1\sim n\) 的排列 \(p\),初始有一个空的无向图,对于所有逆序对 \((i,j)\),在图上连一条 \((i,j)\) 的边,如果这个图是一张三分图,那么我们就称排列 \(p\) 是合法的。现在给出一个长为 \(n\) 的排列 \(q\),你需要求出有多少个排列 \(p\) 满足 \(p\) 的字典序大于 \(q\) 且 \(p\) 是合法的。
多组数据,\(T\le 300,n\le 300\)
首先,如果排列 \(p\) 中存在一个长为 \(4\) 的下降子序列,那么图中会有一个 \(K_4\) 的子图,因为 \(K_4\) 不是三分图,所以排列 \(p\) 不合法。所以排列 \(p\) 不能存在长为 \(4\) 的下降子序列,而根据 Dilworth 引理,排列 \(p\) 一定可以划分为 \(3\) 个不交的上升子序列,而我们刚好可以给每个上升子序列染上一种颜色使得图是三分图,所以 \(p\) 一定合法。于是有排列 \(p\) 合法的冲要条件是 \(p\) 可以划分为 \(3\) 个不交的上升子序列。
先考虑没有 \(q\) 的限制,即计数 \(1\sim n\) 的全排列中有多少个排列合法。首先判断一个序列是否合法可以贪心去做,即从前往后加数,维护当前三个子序列的末尾分别是多少,然后加数时接在符合条件的且末尾最小的子序列上,看能否加完所有数。
于是我们可以 dp,设 \(f_{i,x,y,z}\) 表示加完了前 \(i\) 个数,并且三个子序列的末尾从大到小分别是 \(x,y,z\),转移就枚举下个数是啥。但有个问题是不知道哪些数曾经出现过,所以我们把 \(x,y,z\) 的定义改为它们在 \(1\sim i\) 这些数中的排名是多少,然后枚举下个数在 \(1\sim i\) 中的排名。
然后考虑优化,可以发现 \(x\) 一定等于 \(i\),因为 \(1\sim i\) 中最大的数一定会出现在某个子序列的末尾,于是可以省掉这一维。再将使用前缀和优化,可以做到 \(\mathcal{O}(n^3)\) 的复杂度。
考虑怎么处理询问,因为要求字典序比 \(q\) 大,我们可以枚举 \(p\) 与 \(q\) 的最长公共前缀,然后枚举下一位填哪个数,剩下部分就是任意填排列。那么我们可以将 dp 数组的定义倒过来,即 \(f_{i,x,y}\) 表示已经确定了前面的数,还剩 \(i\) 个数未确定,且当前三个子序列的末尾在后 \(i\) 个数中的排名分别为 \(x,y,1\),后面填数的方案数。转移是枚举第 \(i\) 位填啥,然后 \(f_{i,x,y}\larr f_{i+1,x',y'}\),\(f\) 可以在所有询问前 \(\mathcal{O}(n^3)\) 预处理。
在每个询问中,当我们确定了 \(p\) 的前几位具体是啥后,剩下部分的方案数可以直接访问 \(f\) \(\mathcal{O}(1)\) 求解,于是总复杂度为 \(\mathcal{O}(n^3+Tn^2)\)。
E. 竞赛图
给定 \(n,k\),求有多少个 \(n\) 个点的有标号竞赛图,图中至少存在至少一个 \(k\) 元环。答案对 \(998244353\) 取模。
\(n,k\le 10^5\)
根据竞赛图结论,存在一个 \(k\) 元环就相当于存在一个大小 \(\ge k\) 的强连通竞赛子图。考虑容斥变成求所有强连通分量大小都 \(<k\) 的方案数。记 \(f_n\) 表示大小为 \(n\) 的强连通竞赛图有多少个,\(g_n\) 表示 \(n\) 个点且所有强连通分量大小都 \(<k\) 的竞赛图有多少个,那么可以枚举缩点后链头的强连通分量的大小来进行转移,有:
上述式子显然可以分治 FFT 优化。复杂度 \(\mathcal{O}(nlog^2n)\)。
F. 逆序对
有一个长度为 \(n\) 的 01 序列,一些位置已经确定,还有一些位置没有确定。你需要给所有没确定的位置填上 0 或 1,使得序列的逆序对数最大,输出最大逆序对数。
多组数据,\(n\le 10^6,\sum n\le 2\times 10^6\)
在所有未确定的数中,如果有一个 0 在另一个 1 前面,那么把这两个数交换一定更优。所以最终填法一定是前面一段 1,后面一段 0,枚举断点即可。
G. 丢番图
有一个长为 \(n\) 的正整数序列 \(a\) 和定值 \(t\),你需要求出一个长度为 \(n\) 的非负整数序列 \(x_1,x_2\ldots x_n\),使得对于所有 \(0\le j < n\) 都满足:
\[\sum_{i = 1}^n a_i^j\times x_i\equiv t_j\pmod{998244353} \]保证解唯一。\(n\le 5\times 10^4\)
相当于是求一个向量,满足:
前置知识:伴随矩阵
设 \(M_{i,j}\) 表示矩阵 \(a\) 去掉第 \(i\) 行和第 \(j\) 列后的矩阵的行列式,称为 \(a_{i,j}\) 的余子式。\(A_{i,j}\) 表示 \((-1)^{i+j}M_{i,j}\),称为 \(a_{i,j}\) 的代数余子式。那么对于任意向量 \(x\),\(\sum\limits_{i=1}^n x_i A_{k,i}\) 即为将矩阵 \(a\) 的第 \(k\) 行替换为 \(x\) 后的矩阵的行列式,列同理。
那么对于任意的 \(1\le s,t\le n\),有:
第一个等号相当于把矩阵 \(A\) 的第 \(t\) 行替换为第 \(s\) 行然后求行列式,当 \(s\ne t\) 时,显然行列式为 \(0\),否则为 \(|A|\)。第二个等号同理。
我们定义伴随矩阵为:
即代数余子式的矩阵的转置。有:
如果 \(a\) 是一个可逆矩阵,就可以让等号两边同时乘上 \(a^{-1}\),于是有:\(a^{-1} = \frac{A^*}{|a|}\) 。
Cramer 法则
若线性方程组:
的系数矩阵 \(a\) 是可逆的,则方程有唯一解: \(x_i = \frac{D_i}{|a|}\),其中 \(D_i\) 表示将矩阵 \(a\) 的第 \(i\) 列替换为 \(b\) 的矩阵的行列式。
证明:
方程组可以写为:
等号两边同时在左边乘上 \(a^{-1}\),然后根据 \(a^{-1} = \frac{A^*}{|a|}\),有:
于是 \(\forall 1\le i\le n\),有:
而 \(\sum\limits_{j=1}^n A_{j,i}b_j\) 就相当于把矩阵 \(a\) 的第 \(i\) 列替换为 \(b\) 后的矩阵的行列式,记为 \(D_i\),所以有 \(x_i = \frac{D_i}{|a|}\),即证。
范德蒙德行列式
范德蒙德行列式为:给定 \(n\) 个数 \(a_i\),求:
考虑将第一列除了第一个外的所有元素都消为 \(0\),我们将第 \(n-1\) 行乘 \(-a_1\) 加到第 \(n\) 行,将第 \(n-2\) 行乘 \(-a_1\) 加到 \(n-1\) 行......将第 \(1\) 行乘 \(-a_1\) 加到第 \(2\) 行,于是有:
后面相当于是一个 \(2\sim n\) 的子问题,一直递归下去,可以得到:
考虑 Cramer 法则:\(x_i = \frac{D_i}{|a|}\),\(|a|\) 是一个范德蒙德行列式,\(D_i\) 就相当于把第 \(i\) 列换成了 \(\begin{pmatrix}1\\t\\\vdots\\t^{n-1}\end{pmatrix}\),这仍然是一个范德蒙德行列式。所以:
分子部分可以记录 \((t-a_i)\) 的前缀积和后缀积来求。对于分母部分,可以考虑设多项式 \(F(x) = \prod (x-a_i)\),那么我们要求的就是 \(\frac{F(x)}{x-a_k}\) 在 \(a_k\) 处的取值,考虑洛必达法则:
所以可以先用分治 FFT 求出 \(F(x)\),然后求出 \(F'(x)\),剩下部分就是多点求值。复杂度为 \(\mathcal{O}(n\log^2n)\)。
H. 胡图图
有一个人初始在 \((x,y)\) 处,每一回合他可以走到 \((x\pm 1,y\pm 1),(x\pm 1,y\pm 2),(x\pm 2,y\pm 1),(x\pm 2,y\pm 2)\) 共 \(16\) 个位置中的一个,现在他想走到 \((X,Y)\),求至少需要多少回合。多组询问。
\(T\le 10^6,-10^9\le x,y,X,Y\le 10^9\)
两维是独立的,那么我们可以求出两维分别的答案然后取 \(\max\),即 \(\max(\lceil\frac{|x-X|}2\rceil,\lceil\frac{|y-Y|}2\rceil)\)。
但要注意,步数少的一维需要走一些无用的步直到步数多的一维走完。首先如果两维的步数差 \(\ge 2\),那么一定可以恰好走完(每次可以走 \(2,-1,-1\) 或 \(1,-1\))。如果差为 \(1\),那可以把步数少的一维的某个 \(2\) 拆成 \(1,1\) 或者把某个 \(1\) 拆成 \(2,-1\)。所以有问题的只有可能是一维步数为 \(0\),一维步数为 \(1\),此时的答案为 \(2\),需要特判一下。
I. 本质不同后缀
给定 \(n\) 个字符串 \(S_i\),求本质不同的后缀有多少个。
\(\sum|S_i|\le 3\times 10^5\)
将所有字符串翻转一下,然后可以用字符串哈希,或者全部插入 trie 树或者其他各种方法解决。
J. 四川省赛
给定一个 \(n\) 个点的树,树上每个点有一个大写字符 \(S_u\),求有多少条包含 \(5\) 个点的简单路径,使得这些点的字符依次是 SCCPC
多组数据,\(n\le 10^6,\sum n\le 2\times 10^6\)
dp,设 \(f_{u,i}\) 表示到 \(u\) 这个点,另一端在子树内且匹配了 \(SCCPC\) 的前 \(i\) 位的字符串的点有多少个,\(g_{u,i}\) 表示匹配了第 \(i\sim 5\) 位的有多少个。转移是容易的,计算答案考虑枚举 \(5\) 个点深度最浅的点 \(x\),那么贡献为 \(\sum\limits_{i=1}^5 f_{u,i}g_{u,i}\)。注意有一种情况会算重,即以字符 P 为最浅点时,SCC 和 C 可能会在一个子树内,减掉这种情况即可。
K. 点分治
对于一棵 \(n\) 个点的无根树 \(T\),点编号为 \(1\sim n\),有一个 \(1\sim n\) 的排列 \(p\),操作以下方式生成一棵有根树 \(T'\):
- 找到无根树 \(T\) 在排列 \(p\) 中出现位置最早的点 \(x\);
- 将 \(x\) 从 \(T\) 中删除,并在 \(T'\) 中加入 \(x\) 作为 \(T'\) 的根;
- T 中剩下若干个连通块,每个连通块都是一棵无根树 \(T_i\),对每个 \(T_i\) 都进行操作得到一棵有根树 \(T_i'\)
- 将每棵有根树 \(T_i'\) 加入 \(T\),并将 \(T_i'\) 的根的父亲设为 \(x\)。
现在给定无根树 \(T\) 和排列 \(p\),你需要求出操作后 \(T'\) 上每个点的父亲。
多组数据 \(n\le 10^5,\sum n\le 10^6\)
倒着加点,维护当前树上每个出现过的点形成的连通块中的根节点是啥。每次加入一个点 \(u\),枚举与这个点相连的点 \(v\),如果 \(v\) 已经在排列中出现过,那么就把其所在连通块的根节点的父亲设为 \(u\),用并查集维护即可。
L. abc
定义一个字符串 S 的价值 \(f(S)\) 为出现次数最多的字符的出现次数减去出现次数最少的字符的出现次数,注意出现次数最少的字符必须是要在 S 中出现过的字符。例如 \(f(aaa) = 0,f(abb) = 1,f(cabcc) = 2\)。
现在给定一个长度为 \(n\) 且只包含 abc 的字符串 S,求 \(\sum\limits_{1\le l\le r\le n}f(S[l\ldots r])\)。
\(n\le 2\times 10^5\)
先考虑去掉“出现次数最少的字符必须是要在 S 中出现过的字符”这条限制的答案,可以发现:
于是对于 ab、ac、bc 可以单独统计,假设现在统计 \(\sum|cnt_a-cnt_b|\) 的答案,我们设 \(a_i = \begin{cases}1 & S_i=a \\ -1 & S_i=b \\ 0 & S_i=c\end{cases}\),那么答案就是 \(\sum\limits_{1\le l\le r\le n}|\sum\limits_{i=l}^r a_i|\)。
记 \(s_i\) 为 \(a_i\) 的前缀和,那么答案就是 \(\sum\limits_{1\le l\le r\le n}|s_r-s_{l-1}|\),我们发现一个 \(s_i\) 和 \(i\) 没有关系,只和 \(s_i\) 的具体大小有关。我们将 \(s_i\) 排序,记排序后从小到大为 \(d_i\),那么一个 \(d_i\) 在 \(d_0\ldots d_{i-1}\) 共 \(i\) 个式子中贡献为 \(1\),在 \(d_{i+1}\ldots d_n\) 共 \(n-i\) 个式子中贡献为 \(-1\),所以最终答案为 \(\sum\limits_{i=0}^n d_i(2i-n)\)。
考虑加上限制条件怎么做,首先如果一个串没有同时包含 ab,那么在计算 ab 时就不应该被统计。所以我们将原串去掉 a,对每个极长连续段做上述问题并减去贡献,再将原串去掉 b,同样减掉。对于一个只包含 ab 的串,因为最后答案要除以 \(2\),所以要统计两遍,所以再将原串去掉 c,对每个极长连续段做上述问题并加上贡献。
最后,若一个串只包含 a,那么在统计 abc, ab, ac 的时候都会算上,贡献为 \(1+1-1=1\),但实际上只包含 a 不应该有贡献。所以再对所有 a 的极长连续段做上述问题并减去贡献,b 同理。至此,我们就完成了 ab 的子问题,做三遍这样的问题即可。
时间复杂度为 \(\mathcal{O}(n\log n)\),瓶颈在排序,但是可以发现排序的值域都很小,于是可以用桶排做到线性。

浙公网安备 33010602011771号