W
H
X

2024蓝桥杯省赛C/C++程序设计A组题目简析

2024蓝桥杯省赛C/C++程序设计A组题目简析

A

题意:计算一段区间内日期的中文表达的总笔画数>50的天数

按照题意枚举即可。注意个位数字前面需要加一个“零”,也就是多13笔。

B

题意:\(5\times5\)的棋盘下五子棋,最终下满棋盘并和棋的情况数

dfs或者遍历二进制去枚举棋子位置的情况均可。

假设做法是去枚举黑棋位置的所有情况,一个简单的验证对错的方法是把黑棋的数量分别设置为12/13运行一次,如果答案不等说明写错了。

C

题意:有 \(n\) 个士兵,第 \(i\) 个士兵至少需要训练 $ b_i$ 次,每次训练花费 \(a_i\)。可以每次花钱训练一个士兵,也可以花费 \(S\) 将所有士兵训练一次。求将所有士兵训练达标的最小代价。(\(n\leq 2\times10^5\)

比较明显的贪心算法。先将士兵按照 \(b_i\) 排序,也就是越后面的士兵需要的训练次数越多。从第一个士兵开始往后遍历,做到 \(x\) 时,如果 \(a_x+a_{x+1}+\dots+a_n >S\),那么打包训练更优,做 \(b_x-b_{x-1}\) 次打包训练(\(b_x-b_{x-1}\) 为总共需要次数减去已经执行过的打包训练数);否则,单独训练已经优于打包,直接让答案加上 \([x,n]\) 区间内每个士兵剩下需要单独训练的次数 \(\times\) 训练花费,并退出循环。复杂度 \(O(n\log n)\).

D

题意:有两棵大小分别为 \(n,m\) 的以 \(1\) 为根的树,每个节点有权值,分别为 \(a_i,b_i\)。起初两个人 \(A,B\) 分别站在两棵树的根节点,两人各自一路往下走直到叶子节点,设 \(A\) 经过的结点的权值按照顺序组成序列 \(a_{k_1},a_{k_2},a_{k3}...\)\(B\) 的序列为 \(b_{l_1},b_{l_2},b_{l_3}\dots\),求两个序列的最长公共前缀的可能最大值。(\(n,m\leq 2\times 10^5,\ a_i,b_i\leq 10^9\))

题目转化为:对于第一棵树上的每个节点 \(x\),能否在第二棵树上找到一条一样的从根节点向下的权值路径。

需要快速判断两个序列是否一样,使用哈希函数。先dfs第二棵树,在递归时记录当前节点到根节点 \(1\) 这一段的哈希值,设节点 \(x\)\(1\) 这一段的哈希值为 \(p_x\)

然后dfs第一棵树,记录当前节点的深度和哈希值,设节点 \(y\)\(1\) 这一段哈希值为 \(q_y\),每次只需要看看集合 \(\{p_x\}\) 里是否有 \(q_y\),如果有,说明存在相同路径,答案与 \(y\) 的深度取 \(max\)

复杂度 \(O(n\log n)\)

E

题意:给定一个序列 \(a_1,a_2\dots a_n\),求出最小的 \(x\),使得能够选出 \(a_1,a_2\dots a_x\) 中的 \(k\) 个,使得这 \(k\) 个数的方差小于 \(T\)

\(n\leq 10^5,a_i\leq10^5,T\leq 10^9\)

\(x\) 的可行性单调(即 \(x\) 增长,成功的概率递增),可以二分 \(x\) 得出答案。问题转变成如何判定前 \(x\) 个数是否可行,即求出前 \(x\) 个数中选出 \(k\) 个的最小方差。

为了让方差最小,一定选取排序后相邻的 \(k\) 个数。所以有效的选法只有 \(x-k+1\) 种。将方差的式子拆分括号,变成 \(\sum_{i=1}^{k}x_i^2-\frac{\sum_{i=1}^k x_i}{k}\),得到独立的两个部分,于是只需分别记录 \(\sum_{i=1}^{k}x_i^2\)\(\sum_{i=1}^kx_i\),当区间从 \([p,p+k-1]\) 变成 \([p+1,p+k]\)\(O(1)\) 地修改两个值,就可以算出方差的最小值,进而判定是否可行。

复杂度 \(O(n\log^2n)\) 。可改用倍增避开每次判定的暴力排序优化为 \(O(n\log n)\)

F

题意:给定一棵 \(n\) 个节点的树,树上的节点 \(x\) 的颜色为 \(c_x\)。有 \(q\) 次询问,每次给出两个节点 \(a,b\),问在 \(a,b\) 之间的树上路径上的节点有多少种不同的颜色。

\(n\leq 10^5,c_i\leq 20,q\leq 10^5\)

几乎是树链剖分的模板题。由于颜色的种类很少,只需对每种颜色 \(p\) 开一个数组统计 \(dfs\)序上的颜色为 \(p\) 的结点个数的前缀和,在剖出的每条树链上看看每种颜色有没有即可。

复杂度 \(O(20\ n\log n)\)

G

题意:给定序列 \(x_1,x_2,\dots x_n\),四元组 \((a,b,c,d)\) 是好的当且仅当 \(x_a\)\(x_b\) 整除,\(x_c\)\(x_d\) 整除且 \(a,b,c,d\) 互不相等。问有多少个好的四元组。

\(n\leq 10^5,a_i\leq 10^5\)

观察到 \(a_i\) 的范围并不大,可以用 \(O(\sqrt{a_i})\) 的方法枚举出每个数的因子,然后通过一些数组进行统计,不难得到 \(C_a\):满足 \(a\neq b,\ x_b|x_a\)\(b\) 的数量。

如果没有 \(a,b,c,d\) 不等的条件,只需要考虑 \(a,c\) 的组合,\(b,d\) 的情况为 \(C_a\times C_d\), 总的答案也很好算。

\(a,b,c,d\) 不能相等,考虑容斥。先按照 \(a,c\) 不等,其它随意算出答案 \(ans1\),然后减去 \(a\neq c,b=d\) 的数量 \(ans2\),再减去 \(a\neq c,b\neq d,a=d\) 的数量 \(ans3\)\(a\neq c,b\neq d,b=c\) 的数量 \(ans4\),最后发现 \(a\ne c,a=d,b=c\) 的被减了两次,算出这部分的数量 \(ans5\)。最后答案为 \(ans1-ans2-ans3-ans4+ans5\)\(ans2,3,4,5\) 的计算都类似,不赘述。

容斥的过程稍微有点繁琐,考场上写了对拍,大概是对的。但没考虑到最后答案会超出 \(long\ long\) 的范围......得用 \(int128\) 或者用两个 \(long\ long\) 拼接小小地高精度一下。

H

题意:有 \(n\) 个魔法球和 \(n\) 个空盒子,第 \(i\) 个魔法球的魔法值为 \(a_i\)。现在要将球装入盒子中,每个盒子最多装一个,也可以空着,每个球也最多放入一个盒子中,且相邻的盒子不能放魔法值相同的球。初始体力值为 \(k\),将第 \(i\) 个球装入第 \(j\ (j\leq i)\) 个盒子中消耗 \(i-j\) 体力值。最后放了球的盒子权值 \(v_x\) 为球的魔法值,没放球的盒子 \(v_x=-1\),在保证体力值 \(\ge 0\) 的情况下请移动球使得 \(v_1,v_2,v_3...v_n\) 的字典序最大。

做法挺简单暴力。让字典序最大,自然从 \(1\) 开始往后遍历。遍历到 \(x\) 时,需要找到 \([x,x+k]\) 区间内没被装掉的球里最大的且在所有最大的球里最靠左的那个(尽量节省体力),并把它装入 \(x\)。用线段树维护区间最大值以及区间最大值所在最左端的位置即可,每次执行区间查找、单点修改操作。

但是相邻的两个不能相同,所以还得维护严格次大值和严格次大值最左端的位置,只是让区间合并变得更复杂一些。

复杂度 \(O(n\log n)\)

posted @ 2024-04-17 22:59  -敲键盘的猫-  阅读(598)  评论(0编辑  收藏  举报