AtCoder 竞赛典型 90 题,解题报告
提示:每题括号内的数字大致表示难度。
001 - Yokan Party(★4)
题意
有一个长度为 的纸条。在 个位置 找 个分割点,最大化最短段的长度。
,。
解析
二分最短段的长度 ,贪心来强制每段 ,检验是否能凑出 段。
代码:https://atcoder.jp/contests/typical90/submissions/35153678
002 - Encyclopedia of Parentheses(★3)
题意
按照字典序打印所有长度为 的合法括号序列。
。
解析
是奇数就不输出,否则可以 DFS 解决。
代码:https://atcoder.jp/contests/typical90/submissions/35154547
003 - Longest Circular Road(★4)
题意
给定一棵 个节点的树,加一条边使得构成的环包含点数最多。
。
解析
这个问题等价于求树的直径。(即距离最远的两点的路径经过的点数)
两种解法:
- 利用贪心的想法。先找到距离节点 最远的点 ,再找到距离 最远的点。执行两次 DFS 即可。
- 假设点 为根,对于每个节点 ,找到其子树中最长的两条能接上 的链(不能有交点),把 接上去计算答案。
代码:
- 做法一:https://atcoder.jp/contests/typical90/submissions/35394771
- 做法二:https://atcoder.jp/contests/typical90/submissions/35394830(这个做法本来是 的,但是代码偷懒用了排序)
004 - Cross Sum(★2)
题意
给定一个 的矩阵,对于每个位置 求出所有在第 行或第 列的元素和。
,矩阵元素是 间的整数。
解析
建立分别记录每行、每列元素和的数组,在输入的时候,就将每个数存入对应的位置,最后对于每个位置就可以 查询。
代码:https://atcoder.jp/contests/typical90/submissions/35395190
005 - Restricted Digits(★7)
题意
(题目已运到 YZOJ 5970)
有多少个 位十进制数,满足每位数字都在集合 中,且它是 的倍数?答案对 取模。
任务一:解决 。
任务二:解决 。
任务三:解决 。
集合 内只有 间的整数。
解析
对于任务一,我们设 表示目前已经确定 位,当前数字除以 余 。直接转移是 的。
对于任务二,我们发现 只与 有关,而且第二维大小不超过 ,可以考虑矩阵加速。时间复杂度 。
任务三尚待补充……
006 - Smallest Subsequence(★5)
题意
有一个长度为 的小写字符串 ,请从中找到长度为 且字典序最小的子序列 。
。
解析
根据字典序的策略,只要能保证能凑满 个字母,那尽可能要保证越靠前的字母,它越小。
所以假设当前我们将 定为了 ,那么相当于剩余的 字母,我们要挑 个出来。
那么接下来要填的那个字母可能分布在哪里?在区间 。这是因为我们要保证还没被挑的 个字母有位置。
剩下的任务,就是在区间 内找到最小的字母,同时保证它下标尽量小(为了让后面的挑选范围尽量大)。
这个任务可以使用多标记的线段树。标记存两个东西:区间最小的字母,以及它所在的原串下标(且是尽可能小的)。
细节就不多说了,可以看这份代码:https://atcoder.jp/contests/typical90/submissions/36932587
007 - CP Classes(★3)
题意
数轴上有 个点 ,有 个询问,每次输入一个位置 ,求出距 最近的点到它的距离。
,。
解析
可以二分,也可以排序 + 双指针。注意边界情况。
代码:https://atcoder.jp/contests/typical90/submissions/36932727
008 - AtCounter(★4)
题意
给一个长为 的小写字母串。求有多少个不同的子序列,等于 "atcoder"。
。
解析
观察到 atcoder 这七个字母互不相同,可以设 代表枚举到第 位且分别以 结尾的字符串个数。
转移方程:。时间复杂度 。
代码:https://atcoder.jp/contests/typical90/submissions/36932826
011 - Gravy Jobs(★6)
题意
有 项工作。第 项工作需要在第 天及更早结束,一次耗时 天(不能间断)。完成后可以获得报酬 。
如果一个人一天只能做一项工作,请求出最大报酬。
,。
解析
根据贪心策略,越早截止的工作,应尽早开始完成。所以我们先按照 升序排序。
如果没有截止日期的限制,这就是一个背包问题(截止日期为容量)。
现在加上这个限制,由于工作已经被排序,我们可以认为每次新加入一个工作,背包就会被扩容。
然后就和普通的背包没什么区别了。
代码:https://atcoder.jp/contests/typical90/submissions/36933185
015 - Don't be too close(★6)
题意
给定 。你将得到一个序列 。对于每个 ,求出有多少个子序列满足序列内的元素两两相减绝对值均 。
答案对 取模,。
解析
如果直接动态规划,时间复杂度是 的,过不了。那么考虑问题的组合数学意义!
对于每个 :
- 我们枚举 代表子序列包含的元素个数。
- 容易发现会有 个空隙是不能填数字的,我们将其抽走,那么序列只剩 个位置,供这 个数选取位置。
- 所以对于每个 ,答案即为 。
由于 ,因此预处理组合数的情况下,时间复杂度可以做到 。
代码:https://atcoder.jp/contests/typical90/submissions/37983375
016 - Minimum Coins(★3)
题意
有三种面值的硬币 。问最少多少个硬币可以支付恰好 元。
,答案 。
解析
直接枚举 ,可以间接求出 ,然后比较答案。
代码:https://atcoder.jp/contests/typical90/submissions/38166776
019 - Pick Two(★6)
题意
有一个长为 的序列 。每次选中当前相邻的两个数 ,删除它们,代价是 。
每次把两个数删除后,剩下的序列会拼在一起。问删光序列的最小代价和。
,。
解析
每次都是删除当前序列的两个相邻位置的数,那么如果原序列两个数正在被删除,就代表它们之间的数已经删光了。
所以可以上区间 DP。 表示将序列子区间 删空的最小代价。
( 为偶数且大于等于 )有两种构成方式:
- 将 拆成两个偶数段,相加取最小值;
- 将 拆成两个偶数段,相加,并加上 取最小值。
如上转移即可。时间复杂度 。
代码:https://atcoder.jp/contests/typical90/submissions/37984053
020 - Log Inequality(★3)
题意
比较 与 的大小。
,,。
解析
两边变指数,分别变为 与 比大小。
代码:https://atcoder.jp/contests/typical90/submissions/38166870
025 - Digit Product Equation(★7)
题意
定义 表示 十进制下每位数字的乘积(不含前导 )。
求 有多少数 满足 。
。
解析
先枚举当前有几个数位。对于每个数位 DFS 一次。
看到这有人会问:这范围那么大,DFS 不会搜爆掉吗?OK,我们来分析一下怎么搜。
没有剪枝的时候,每个数位都有 种可能,但实际上这会产生很大的效率浪费。
比如 这六个数,它们的 均为 。
然后 是固定的,可以知道此时 已经被确定下来了。所以这 个数最多只会有一个是符合条件的。
这个事情告诉我们,我们在搜索数字的时候,可以强制后面的数位大于等于前面的数位。
之后,我们需要判断,将当前的 数位改变一些顺序,能不能使得它等于定值 。
此时不需要大费周章去全排列枚举,只需要将 和 两数的数位分别升序排列,比较这两个序列相同情况就可以了。
注意判断数字是否在上界 以内。
这个做法时间复杂度并不好计算,但是可以写个程序测试一下,可以发现这种方式生成的 不到 个。
代码:https://atcoder.jp/contests/typical90/submissions/37100318
029 - Long Bricks(★5)
题意
一条直线按顺序有 个位置,接下来天上会掉下来 个横条形的俄罗斯方块。
第 个方块占据了位置 。根据俄罗斯方块规则,它会一直下落直到底面的某处碰到了地面或别的方块。
如果每个俄罗斯方块高为 ,请求出每个方块停止下落的时候,它所在的高度。
,。
解析
本题涉及到区间求 ,区间修改,是个经典的线段树维护懒标记的题目。
由于这题比较模板,就不多说了,具体细节可以看代码:https://atcoder.jp/contests/typical90/submissions/38139303
030 - K Factors(★5)
题意
给定 , 有多少个正整数,它至少有 个素因数?
,。
解析
两个做法:
- 埃氏筛法,每个质数向后跳倍数,时间复杂度 。
- 线性筛。记 表示数字 的最大素因子,设数字 的质因子数为 ,那么可以 转移,如下:
代码(第一种做法):https://atcoder.jp/contests/typical90/submissions/38139369
039 - Tree Distance(★5)
题意
给定一棵 个节点的树,树上的边边权均为 ,求树上两两节点距离之和。
。
解析
这是一个经典的树上换根 DP 题。下面简述下解法:
- 第一步,用一次 DFS 遍历算出以 号节点为根,到其它每个点的距离 ,以及每个节点以自己为根的子树大小 。
- 设此时的距离和为 。
- 第二步,换根。同样按照 DFS 遍历顺序,如果以前根为 ,此时根从 换成 。
- 对于 此时将变成 。因为就 及其子树而言,它到新根的距离都减少了 ;就子树 以外的节点而言,它到新根的距离都增加了 。
- 将每个点为根时的 相加,就是答案。
注意 DFS 回溯时要还原信息。代码:https://atcoder.jp/contests/typical90/submissions/38139648
066 - Various Arrays(★5)
题意
见 YZOJ 5973。
有一个长度为 的序列 。其中 将从 区间中随机抽取一个整数作为它的值。
请求出整个序列的逆序对的期望数。
原题范围:,。
加强版范围:, 在保证存在 double 内精度正常的情况下无特殊限制。
解析
由期望的线性性,整个逆序对的期望数,等于两两位置比较,产生的逆序对的期望数。
而所谓两两位置比较的逆序对,就是位置靠前的数大于位置靠后的数的概率!
所以先两两枚举下标 ,接着 也逐个枚举,判断它们的大小,累加后除以总数即得到概率。
时间复杂度 级别( 与 同阶),通过前缀和优化可以达到 。
对于加强版,我们就不能逐个枚举 的值了,而是直接根据这两组 比较 的概率。
此时要分六类讨论:
- ,易知概率为 ;
- ,易知概率为 ;
- ,分开考虑区间 与 的相交片段的概率,和分离片段的概率。
- ,同上一种情况。
- ( 是 的子区间);
- ( 是 的子区间)。
此时时间复杂度 。代码:https://atcoder.jp/contests/typical90/submissions/38141000
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话