- gf24240 的博客
CSP 模拟赛
- @ 2026-8-21 12:08:32
前言
距离 2026 CSP 第二轮还有 71 天。
简单
T1-生产线
题意:按照 个 和 个 排列,问前 个数中有多少个 。
可以发现 是个循环节,循环节内有 个 。可以通过 计算有多少个循环节。去掉循环节后剩下 除以 个数,计算这些数中有多少个 (与 取 )即可。答案:$\lfloor \frac{n}{a+b} \rfloor \times a + \min(n - \lfloor \frac{n}{a+b} \rfloor, a)$
T2-三数之和
题意:找出三个小于等于 的数使其和为 的方案数。
注意到 ,数据非常小。可以枚举前两个数,做差求出第三个数。统计数量即可。
T3-数学老师的难题
题意:求 ~ 的因数个数和。
可以通过前缀和转化为 ~ 的因数个数和减去 ~ 的因数个数和。定义 表示 到 的因数个数和,那么答案就是 。
:直接分别求 ~ 的因数个数不好求。可以反过来想:枚举因数 ,计算有多少个数是 的倍数。倍数自然就是 。 从 到 。,不会超时。
T4-小蛮腰
题意:用 星号能组成的最大的小蛮腰。
- 找规律 + 二分:通过观察可以知道边长和需要的个数的关系。再二分查找剩余最少的。
- 枚举:可以发现图形是对称的,第 次增加 个星号。直到总和超过 ,输出上一个就好了。
T5-批量更新
题意:有一个数组,每次操作将值为 的都改成 并输出总和。
可以使用桶排,存储库存为 的有多少个。修改时(库存 ):。总和就加上 。
普及 +
注意到这个比赛是 “普及+”,对于洛谷难度 “普及+/提高”。
T1-试吃(eat)
目标:通过反复操作,让所有 个人的口味都变成同一种。
操作规则:每次选一个连续区间 ,如果这个区间里超过半数的人喜欢同一种口味 ,那么区间里所有人都会变成口味 。
问题:哪些口味有可能最终成为所有人的统一口味?
假设我们每次都只选连续 个人试吃。此时问题就非常简单: 个人中,只要有 个人口味一致,就能将这三个人统一。
如果三个人口味统一了,那就能拓展到 个人。 个人就能拓展到 个人。反正,只需要考虑连续 人。所有数字塞进 set 里,最后输出就好了。
T2-工作任务(work)
题意:两个列表 和 ,从头往后取数。使总和不超过 最多能取多少个数。
首先可以考虑暴力。枚举 中选前 个,内层枚举 中选前 个。然后计算 ,如果没有超过 就更新答案。
容易想到上面那一坨东西可以用前缀和优化,这样就优化到 。不过还是会超时。 和 都是正整数,容易发现做够前缀和后是单调的。此时可以用二分查找 能选到第几个数。时间复杂度就是 。
既然是单调的,那 的位置就会一直往前而不会后退。那就可以用双指针。开始时 都指向 (什么都不选)。在 后移的过程中,如果 就将 后移,并更新答案。这样时间复杂度就优化到 。
提醒
下面 ↓ 几题我的代码都又臭又长,只能提供大概的思路了。
T3-学习计划(study)
题意:每个学生有初始分数和每天增长的分数。问多少天能达到校长给定的排名。
可以先按照排名 升序排序。然后对于每个人,计算 需要多少天能超过 ,答案就是所有天数中的最大值。如果有一个人不能超过,那就是不行。同时还需要计算 能比 高的最后一天。因为如果 本来就比 高并且 相对于 是下滑的,那就有可能有最后一天。
然后有两个全局的 和 计算所有情况都满足的第一天和最后一天。遍历完后如果 是个合法的范围,就输出 ,否则就输出 。
T4-魔法井字棋(magic)
这题的 非常小,只有 。可以直接用 DFS 遍历每一种情况。注意打标记的时候要把棋盘状态和节点位置一起标记了,最后对棋盘状态进行去重。
还可以优化(我的做法):用 DFS 遍历棋盘可能会遍历到很多无用的空格子。所以可以在 DFS 前对每个 B/M/O 做 BFS,找到可以直接相连的 B/M/O,用邻接链表存图。之后对这个图进行 DFS 就会快很多。
T5-邮票收集(stamp)
可以使用动态规划。
- 定义状态变量:定义
dp[i][j]表示使用前 个字母,拼出长度恰好为 的邮票序列的方案数。 - 状态转移方程:首先要枚举 ,分别从 到 和 。然后枚举选 个字母 。 就可以加上 选择前 个字母恰好拼出 的方案数乘以在 个位置中选出 个放 。即 。计算组合数 可以直接用公式 。
- 初始化和边界:,用 个字母拼出长度微为 只有一种方案,就是什么都不做。
- 答案:所有长度都是可以的,所以答案:。
需要注意的地方:需要取模,所以组合数中的除法要改成乘以逆元。而且 是个质数,。不过也可以用递推直接求出组合数。但我不会。
T6-音符序列(seq)
(提示:我的这个做法有些点竟然要 900ms 以上,非常不推荐)
题意:对字符串 进行一些操作,修改某个字符或判断 是否是 排序后的子串。
可以用线段树维护区间内每种字母的出现次数(这要是二维的,要不就开 个线段树),再用树状数组维护区间是否顺序(如果 则为 ,否则为 )
操作一:
- 将 字母对应的线段树 上的数减一。对应的将 线段树上第 加一。
- 要将 替换为 。如果 ,则将树状数组的第 项设为 。如果 ,则将树状数组的第 项设为 。
- 将 修改为 。
操作二:这有两条性质:
- 如果是 的子串,那么 这一段必须升序。
- 而且 内所有字符数量都必须和整体的数量一致。