[CodeForces] CF998 题解
注:难度评级为 D 到 A,对标 NOIP T1 到 T4。+ 表示比原本难,- 反之。例如,D+ 比 D 难。难度评级仅供参考。 如果认为难度评级与实际难度不符,可以在评论区@我进行讨论。
Upd 2024/11/18 10:01:将 E 题的实现难度 D+ 改为了 C。增加了一些说明。
A. Ballon
【难度分析】
思维难度:D-
实现难度:D-
总体难度:D-
评级: 普及-
【题目大意】
\(n\) 个物品,第 \(i\) 个物品权值为 \(a_i\),分成 \(2\) 堆,每堆至少有 \(1\) 个物品,并且两堆的权值和不相等。如果存在一种分法,输出任意一种分法中,任意一堆的物品数量与物品编号。否则输出 \(-1\)。
- \(1 \leq n \leq 10, 1 \leq a_i \leq 10^3\)
【解题思路】
考虑这样一种构造:权值最小的物品一堆,其他的一堆。
- 在 \(n = 1\) 或 \(n = 2\) 且 \(a_1 = a_2\) 时。显然,无论如何分都不能使两堆权值和不相等。
- 其他情况,容易证明它是成立的。
B. Cutting
【难度分析】
思维难度:D
实现难度:D-
总体难度:D-
评级: 普及/提高-
【题目大意】
给定一个序列 \(a\),奇数个数和偶数个数相同。你可以进行若干次切割操作。如果你在 \(i\) 位置后面切割,序列会被分为两段,这次切割的花费为 \(\lvert a_{i + 1} - a_i \rvert\)。你需要保证,在所有的切割之后,每段序列的奇数个数和偶数个数相同,我们称这样的切割是合法的。你需要在总花费不超过 \(B\) 的情况下,最大化切割的次数。
例:对序列 \([4, 1, 2, 3, 4, 5, 4, 4, 5, 5]\) 进行两次切割操作后,变为 \([4, 1], [2, 3, 4, 5], [4, 4, 5, 5]\),它是一个合法的切割。
- \(1 \leq n \leq 100, 1 \leq B \leq 100, 1 \leq a_i \leq 100\)
【解题思路】
令 \(f_i\) 表示 \(a_1\) 到 \(a_i\) 中,奇数个数与偶数个数的差。\(f_i\) 容易通过预处理出。这样,区间 \([l, r]\) 中,奇数个数与偶数个数的差就是 \(f_r - f_{l - 1}\)。
对于区间 \([l, r]\) 来说,如果需要操作合法,那么就要使这个区间内奇数个数与偶数个数的差为 \(0\)。因为如果这个值不为 \(0\),那么无论经过多少次切割之后,必会留下一个区间,它的奇数个数不等于偶数个数。这是显然的。
由于 \(f_0 = 0, f_n = 0\),所以我们每次切割时,必须选择 \(f_i = 0\) 的位置 \(i\) 切割。否则必定有一个区间的 \(f_r - f_{l - 1}\) 不为 \(0\)。
这样,我们就知道了合法的切割位置,每次我们可以贪心地选取花费少的区间进行切割,这样可以最大化我们的切割次数。用堆维护就可以。
C. Convert to Ones
【难度分析】
思维难度:D
实现难度:D-
总体难度:D
评级: 普及/提高-
【题目大意】
给你一个长度为 \(n\) 的 \(01\) 串,你可以进行以下操作:
- 翻转一个字串,花费为 \(x\)
- 反转(将 \(0\) 变成 \(1\),\(1\) 变成 \(0\))一个字串,花费为 \(y\)
求你将这个 \(01\) 串变成全是 \(1\) 的串的最少花费。
【解题思路】
我们注意到一个性质:操作的代价与子串长度无关。
这就意味着,连续的 \(0\) 与单个的 \(0\) 没有区别。接下来的讨论将这些连续段每个缩为一个 \(0\),同时令 \(k\) 为连续段的数量。
那么,我们的目标是将 \(0\) 删除。对于两个最近的 \(0\),我们可以进行一次字串翻转,使他们变成相邻的 \(0\),最后可以一并反转删除。当然我们也可以直接反转一段,减少一个 \(0\) 的数量。
如果 \(x < y\),那么翻转操作更优,我们需要翻转 \(k - 1\) 次,把它变成一个连续段,然后一并反转删除,代价为 \(x \times (k - 1) + y\)。否则,一个个反转删除,代价为 \(y * k\)。
所以总代价为 \(\min(x, y) \times (k - 1) + y\)。需要特判 \(k = 0\) 的情况,此时总代价为 \(0\)。
D. Roman Digits
【难度分析】
思维难度:B
实现难度:D-
总体难度:C+
评级: 提高+/省选-
【题目大意】
罗马数字只有 \(4\) 个字符,\(\tt{I, V, X, L}\) 分别代表 \(1, 5, 10, 50\)。一个罗马数字的值为该数字包含的字符代表数字的和,而与字符的顺序无关。例如 \(\tt{XXXV} = 35\),\(\tt{IXI} = 12\)。
现在求一个长度为 \(n\) 的罗马数字可以有多少种不同的值。
- \(1 \leq n \leq 10^9\)
【解题思路】
打表找规律题。
通过打表可以发现,前面 \(11\) 项是定值,后面是公差为 \(49\) 的等差数列。证明有待完善。
E. Sky Full of Stars
【难度分析】
思维难度:B+
实现难度:C
总体难度:B
评级: 省选/NOI-
【题目大意】
有一个 \(n \times n\) 的正方形网格。用红色,绿色,蓝色三种颜色染色,求有多少种染色方案使得至少一行或一列是同一种颜色。结果对 \(998244353\) 取模。
- \(1 \leq n \leq 10 ^ 6\)
【解题思路】
本题公式较多,请仔细阅读。
令 \(f(i, j)\) 表示有 \(i\) 行和 \(j\) 列被染成相同颜色的方案数(\(i \times j > 0\))。则有
将 \(i \times j = 0\) 的答案 \(A1\) 单独考虑,则有
其余的答案记为 \(A2\),则有
记总答案为 \(Ans\),则有
由于计算 \(A2\) 的复杂度是 \(O(n ^ 2)\) 的,所以考虑化简 \(A2\)。
考虑换元,\(i\gets n - i\),\(j \gets n - j\),则有
继续化简,有
注意到有
那么有
这样,我们就可以通过通过 \(O(n\log n)\) 的复杂度计算 \(A2\) 了(那个 \(\log\) 是快速幂的复杂度)。
最后,有总答案
实现较为简单。