扩大
缩小

AtCoder 竞赛典型 90 题,解题报告

提示:每题括号内的数字大致表示难度。

001 - Yokan Party(★4)

题意

有一个长度为 L 的纸条。在 N 个位置 a1,a2,...,anK 个分割点,最大化最短段的长度。

1KN1050<a1<a2<...<an<L109

解析

二分最短段的长度 l,贪心来强制每段 l,检验是否能凑出 k+1 段。

代码:https://atcoder.jp/contests/typical90/submissions/35153678

002 - Encyclopedia of Parentheses(★3)

题意

按照字典序打印所有长度为 n 的合法括号序列。

1n20

解析

n 是奇数就不输出,否则可以 DFS 解决。

代码:https://atcoder.jp/contests/typical90/submissions/35154547

003 - Longest Circular Road(★4)

题意

给定一棵 n 个节点的树,加一条边使得构成的环包含点数最多。

1n105

解析

这个问题等价于求树的直径。(即距离最远的两点的路径经过的点数)

两种解法:

  1. 利用贪心的想法。先找到距离节点 1 最远的点 p,再找到距离 p 最远的点。执行两次 DFS 即可。
  2. 假设点 1 为根,对于每个节点 x,找到其子树中最长的两条能接上 x链(不能有交点),把 x 接上去计算答案。

代码:

  • 做法一:https://atcoder.jp/contests/typical90/submissions/35394771
  • 做法二:https://atcoder.jp/contests/typical90/submissions/35394830(这个做法本来是 O(n) 的,但是代码偷懒用了排序)

004 - Cross Sum(★2)

题意

给定一个 H×W 的矩阵,对于每个位置 (i,j) 求出所有在第 ij 列的元素和。 

1H,W2000,矩阵元素是 [1,99] 间的整数。

解析

建立分别记录每行、每列元素和的数组,在输入的时候,就将每个数存入对应的位置,最后对于每个位置就可以 O(1) 查询。

代码:https://atcoder.jp/contests/typical90/submissions/35395190

005 - Restricted Digits(★7)

题意

(题目已运到 YZOJ 5970)

有多少个 N 位十进制数,满足每位数字都在集合 S 中,且它是 B 的倍数?答案对 109+7 取模。

任务一:解决 N10000,B50

任务二:解决 N1018,B50

任务三:解决 N1018,B1000

集合 S 内只有 19 间的整数。

解析

对于任务一,我们设 dpi,j 表示目前已经确定 i 位,当前数字除以 Bj。直接转移是 O(NB2) 的。

对于任务二,我们发现 dpi,j 只与 dpi1,k 有关,而且第二维大小不超过 50,可以考虑矩阵加速。时间复杂度 O(B3logN)

任务三尚待补充……

006 - Smallest Subsequence(★5)

题意

有一个长度为 N 的小写字符串 S,请从中找到长度为 K 且字典序最小的子序列 T

1KN105

解析

根据字典序的策略,只要能保证能凑满 K 个字母,那尽可能要保证越靠前的字母,它越小。

所以假设当前我们将 Tp 定为了 Sq,那么相当于剩余的 Nq 字母,我们要挑 Kp 个出来。

那么接下来要填的那个字母可能分布在哪里?在区间 [Nq, Nq(Kp1)]。这是因为我们要保证还没被挑的 Kp1 个字母有位置。

剩下的任务,就是在区间 [Nq, Nq(Kp1)] 内找到最小的字母,同时保证它下标尽量小(为了让后面的挑选范围尽量大)。

这个任务可以使用多标记的线段树。标记存两个东西:区间最小的字母,以及它所在的原串下标(且是尽可能小的)。

细节就不多说了,可以看这份代码:https://atcoder.jp/contests/typical90/submissions/36932587

007 - CP Classes(★3)

题意

数轴上有 n 个点 a1,a2,...,an,有 q 个询问,每次输入一个位置 x,求出距 x 最近的点到它的距离。

N,Q3×1050ai,x109

解析

可以二分,也可以排序 + 双指针。注意边界情况。

代码:https://atcoder.jp/contests/typical90/submissions/36932727

008 - AtCounter(★4)

题意

给一个长为 N 的小写字母串。求有多少个不同的子序列,等于 "atcoder"。

N105

解析

观察到 atcoder 这七个字母互不相同,可以设 dpi,0/1/2/3/4/5/6 代表枚举到第 i 位且分别以 a,t,c,o,d,e,r 结尾的字符串个数。

转移方程:dpi,j=dpi1,j[tj=si]。时间复杂度 O(n)

代码:https://atcoder.jp/contests/typical90/submissions/36932826

011 - Gravy Jobs(★6)

题意

n 项工作。第 i 项工作需要在第 di 天及更早结束,一次耗时 ci 天(不能间断)。完成后可以获得报酬 si

如果一个人一天只能做一项工作,请求出最大报酬。

1n,di,ci50001si109

解析

根据贪心策略,越早截止的工作,应尽早开始完成。所以我们先按照 di 升序排序。

如果没有截止日期的限制,这就是一个背包问题(截止日期为容量)。

现在加上这个限制,由于工作已经被排序,我们可以认为每次新加入一个工作,背包就会被扩容。

然后就和普通的背包没什么区别了。

代码:https://atcoder.jp/contests/typical90/submissions/36933185

015 - Don't be too close(★6)

题意

给定 n。你将得到一个序列 1,2,...,n。对于每个 x=1,2,3,...,n,求出有多少个子序列满足序列内的元素两两相减绝对值均 x

答案对 109+7 取模,1n105

解析

如果直接动态规划,时间复杂度是 O(n2) 的,过不了。那么考虑问题的组合数学意义!

对于每个 x (x1)

  • 我们枚举 t=1nx 代表子序列包含的元素个数。
  • 容易发现会有 (x1)(t1) 个空隙是不能填数字的,我们将其抽走,那么序列只剩 n(x1)(t1) 个位置,供这 t 个数选取位置。
  • 所以对于每个 x,答案即为 i=1nx(n(x1)(i1)i)

由于 i=1+ni=lnn,因此预处理组合数的情况下,时间复杂度可以做到 O(nlnn)

代码:https://atcoder.jp/contests/typical90/submissions/37983375

016 - Minimum Coins(★3)

题意

有三种面值的硬币 A,B,C。问最少多少个硬币可以支付恰好 N 元。

1A,B,C,N109,答案 9999

解析

直接枚举 A,B,可以间接求出 C,然后比较答案。

代码:https://atcoder.jp/contests/typical90/submissions/38166776

019 - Pick Two(★6)

题意

有一个长为 2n 的序列 a1,a2,...,a2n。每次选中当前相邻的两个数 ai,ai+1,删除它们,代价是 |aiai+1|

每次把两个数删除后,剩下的序列会拼在一起。问删光序列的最小代价和。

n200ai106

解析

每次都是删除当前序列的两个相邻位置的数,那么如果原序列两个数正在被删除,就代表它们之间的数已经删光了。

所以可以上区间 DP。dpi,j 表示将序列子区间 [i,j] 删空的最小代价。

dpi,jji+1 为偶数且大于等于 4)有两种构成方式:

  • [i,j] 拆成两个偶数段,相加取最小值;
  • [i+1,j1] 拆成两个偶数段,相加,并加上 |aiaj| 取最小值。

如上转移即可。时间复杂度 O(n3)

代码:https://atcoder.jp/contests/typical90/submissions/37984053

020 - Log Inequality(★3)

题意

比较 log2ablog2c 的大小。

1a9×10181b171c13

解析

两边变指数,分别变为 acb 比大小。

代码:https://atcoder.jp/contests/typical90/submissions/38166870

025 - Digit Product Equation(★7)

题意

定义 f(x) 表示 x 十进制下每位数字的乘积(不含前导 0)。

1N 有多少数 x 满足 xf(x)=B

1N,B1011

解析

先枚举当前有几个数位。对于每个数位 DFS 一次。

看到这有人会问:这范围那么大,DFS 不会搜爆掉吗?OK,我们来分析一下怎么搜。

没有剪枝的时候,每个数位都有 10 种可能,但实际上这会产生很大的效率浪费。

比如 123,132,213,231,312,321 这六个数,它们的 f(x) 均为 6

然后 B 是固定的,可以知道此时 B+f(x) 已经被确定下来了。所以这 6 个数最多只会有一个是符合条件的。

这个事情告诉我们,我们在搜索数字的时候,可以强制后面的数位大于等于前面的数位

之后,我们需要判断,将当前的 x 数位改变一些顺序,能不能使得它等于定值 f(x)+B

此时不需要大费周章去全排列枚举,只需要将 xf(x)+B 两数的数位分别升序排列,比较这两个序列相同情况就可以了。

注意判断数字是否在上界 N 以内。

这个做法时间复杂度并不好计算,但是可以写个程序测试一下,可以发现这种方式生成的 x 不到 5×105 个。

代码:https://atcoder.jp/contests/typical90/submissions/37100318

029 - Long Bricks(★5)

题意

一条直线按顺序有 W 个位置,接下来天上会掉下来 n 个横条形的俄罗斯方块。

i 个方块占据了位置 [Li,Ri]。根据俄罗斯方块规则,它会一直下落直到底面的某处碰到了地面或别的方块。

如果每个俄罗斯方块高为 1,请求出每个方块停止下落的时候,它所在的高度。

1LiRiW5×1051N2.5×105

解析

本题涉及到区间求 max,区间修改,是个经典的线段树维护懒标记的题目。

由于这题比较模板,就不多说了,具体细节可以看代码:https://atcoder.jp/contests/typical90/submissions/38139303

030 - K Factors(★5)

题意

给定 N,K1N 有多少个正整数,它至少有 K 个素因数?

2N107K8

解析

两个做法:

  • 埃氏筛法,每个质数向后跳倍数,时间复杂度 O(nloglogn)
  • 线性筛。记 fac(i) 表示数字 i 的最大素因子,设数字 x 的质因子数为 f(x),那么可以 O(n) 转移,如下:

f(x)=f(xfac(x))+[fac(xfac(x))fac(x)]

代码(第一种做法):https://atcoder.jp/contests/typical90/submissions/38139369

039 - Tree Distance(★5)

题意

给定一棵 n 个节点的树,树上的边边权均为 1,求树上两两节点距离之和。

2n105

解析

这是一个经典的树上换根 DP 题。下面简述下解法:

  • 第一步,用一次 DFS 遍历算出以 1 号节点为根,到其它每个点的距离 d(i),以及每个节点以自己为根的子树大小 size(i)
  • 设此时的距离和为 S
  • 第二步,换根。同样按照 DFS 遍历顺序,如果以前根为 x,此时根从 x 换成 y
  • 对于S 此时将变成 Ssize(y)+nsize(y)。因为就 y 及其子树而言,它到新根的距离都减少了 1;就子树 y 以外的节点而言,它到新根的距离都增加了 1
  • 将每个点为根时的 S 相加,就是答案。

注意 DFS 回溯时要还原信息。代码:https://atcoder.jp/contests/typical90/submissions/38139648

066 - Various Arrays(★5)

题意

见 YZOJ 5973。

有一个长度为 n 的序列 a1,a2,...,an。其中 ai 将从 [Li,Ri] 区间中随机抽取一个整数作为它的值。

请求出整个序列的逆序对的期望数

原题范围:1n1001LiRi100

加强版范围:1n5000Ri 在保证存在 double 内精度正常的情况下无特殊限制。

解析

由期望的线性性,整个逆序对的期望数,等于两两位置比较,产生的逆序对的期望数。

而所谓两两位置比较的逆序对,就是位置靠前的数大于位置靠后的数的概率

所以先两两枚举下标 i,j (ij),接着 ai,aj 也逐个枚举,判断它们的大小,累加后除以总数即得到概率。

时间复杂度 O(n4) 级别(nai 同阶),通过前缀和优化可以达到 O(n3)

对于加强版,我们就不能逐个枚举 ai,aj 的值了,而是直接根据这两组 [Li,Ri],  [Lj,Rj] 比较 ai>aj 的概率。

此时要分六类讨论:

  • Ri<Lj,易知概率为 0
  • Li>Rj,易知概率为 1
  • LiLjRiRj,分开考虑区间 [Li,Ri][Lj,Rj] 的相交片段的概率,和分离片段的概率。
  • LjLiRjRi,同上一种情况。
  • LjLiRiRjij 的子区间);
  • LiLjRjRiji 的子区间)。

此时时间复杂度 O(n2)。代码:https://atcoder.jp/contests/typical90/submissions/38141000

posted @   HoshizoraZ  阅读(642)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示