CF1879ABC个人题解
题目链接:Dashboard - Educational Codeforces Round 155 (Rated for Div. 2) - Codeforces
A. Rigged!
有一场比赛, 一共有n个人,每个人的力量是si
, 耐力是ei
,现在有一个哑铃,哑铃的重量是w
,如果第i个人的力量不低于哑铃的重量,则可以把他举起来,并且可以举ei
次,也就是耐力值,那么他得到的分数也就是ei
;比赛获胜的条件是:对于一个哑铃,有且只有一人的分数最高则获胜,若存在有多人分数并列第一则视为没有获胜。
主办方Monocarp
希望自己的好朋友Polycarp
(第一个人)能够赢下比赛(他的分数最高且高于其他所有玩家),那么请计算monocarp
得将哑铃的重量设置为多少,Polycarp
才能赢下比赛?
思路:贪心。
- 如果一个人比
Polycarp
力量小,则设置为比他力量大的重量, 但小于等于Polycarp
的力量,这样他的分数就是0分,而Polycarp
的分数为ei
; - 如果一个人的力量比
Polycarp
大,但耐力没有Polycarp
高,那么把哑铃设置为小于等于Polycarp
的力量的值,那么Polycarp
的分数还是比这个人高。 - 如果存在比
Polycarp
的力量大,且耐力还要好的人,则永远不能获胜。
那么答案就出来了。w的重量一个在一个范围内:小于Polycarp
的力量的所有人的最大力量值到Polycarp
的力量值,这个区间内的所有答案都正确,那么我们为什么不直接取Polycarp
的力量呢?
|
B. Chips on the Board
给定两个长度为n的正整数数组a和b,现在有一个n*n的矩阵m,矩阵中每一个单元格的value是
现在你将进行以下几次操作:
- 选中一个单元格并标记它,那么花费的代价就是该单元格的value
最后,你需要满足:对于矩阵中所有的单元格来说,该单元格所在行或所在列至少有一个被标记了的单元格。
对于此样例来说,选择这三个单元格的代价是最小的。
思路:对于上面的样例来说,第三排第二个其实可以换到第一排第二个的位置。
贪心。能把四个样例看懂了,就知道怎么做了。
答案是:
最好的答案是直接选择一列,或者一行。
|
C. Make it Alternating
给定一个二进制字符串s(仅包含01).
现在你可以进行任意次以下操作:(可以不操作)
- 选择一个,并删除.
当你操作完后,最后的s字符串应该是一个交替的二进制字符串,即任何相邻的两个字符不能相同。
你需要计算两个value:
- 需要操作的次数。
- 不同操作序列的个数。即:进行n次操作后使得二进制字符串交替;这n个选定的i不同,则视为操作序列不同,比如:[1, 2], [2, 1] 先删除2再删除1和先删除1在删除2都能够使得二进制字符串交替,且顺序不同,视为两个不同的序列。
思路:
首先得先知道我们得删除多少个字符串
对于一段连续相同的子字符串,我们应该只留下1个字符,剩余的全部删掉。
比如样例:
- 10010: 连续的两个0我们只能留下一个,删除一个;
- 111: 连续的三个1我们只能留下一个,删除两个;
- 1100:同上,需要删除1个1、1个0;
111000111: 需要删除2个1、2个0、2个1。
那么第一个value我们就求出来了:
对于第二个value我们应该如何计算呢?
首先根据题意我们知道,这一定是一个排列组合:对于上面第三个样例,我们可以进行:(这里暂时不考虑删除后导致其他字符的位置发生改变)
- [1, 3]
- [1, 4]
- [2, 3]
[2, 4]
这是顺序过来的,当然也可以进行反序:(这很重要!)[3, 1]
- [3, 2]
- [4, 1]
[4, 2]
我们将所有需要删除的字符放进一个数组中,这个数组存储着:连续相同的字符个数(长度大于1的)。
那么对于,我们就需要删除个字符。
有同学可能会想到答案是:,也就是高中学的排列组合,第1段我们选择个人进行排列、第2段我们选择个人进行排列…然后将所有的组合相乘就是答案了。
那么恭喜你,你已经接触到答案的边缘了,but,这还是错的,有一个非常重要的问题:
我们这样操作:,实际上是固定了,我们先从第一段开始,删完了再删除第二段…一直删到最后一段。这个顺序是从前往后的,但是答案是什么?答案不仅仅包含整个,比如上面的举例,他还可以从后往前。那么到底是那些顺序呢?答案是无序的,任意顺序都可以。比如三段:中间的可以是最先开始的,也可以是最后开始的,也可以是第二次开始的,答案应该都包含这些顺序。并且一段连续的需要删除的,我们也完全可以在这两个操作中间插入一个别的操作。所以重点是无序!,不仅仅是连续的无序,更是单个操作无序;虽然要求二进制字符串是交替的,但是并没有要求我们的操作也是交替的或者必须是连续的!
比如:
111000
v数组:3 3
那么我既可以先删除后面的0,在删除前面的1;也可以先删除后面1个0,在删除前面两个1,在删除…
所以对于答案:来说是片面的。
那么正确的做法是什么呢?
对于第i段:,我们应该选择出个人出来(保证每次选择的人不同即可),然后对这个人进行全排列,就是答案了:
对于第i段:,我们应该选择出个人出来(保证每次选择的人不同即可,所以得用组合)一共有多少种选法呢?
那么对于所有的来说,这样一共会有多少种选法?
最后再乘以这个人的全排列就行了。
所以最后的答案就是:
考虑:
对于答案2,如果计算长度为1的值,会影响最终答案嘛?
答案:不会,注意看公式,左边累乘1不会有任何影响、右边累加0也不会有任何影响。
是否需要预处理计算函数。
答案:最好需要,因为这是一个纯函数,纯函数:相同的输入只会有相同的输出,不会受外界干扰,不会导致副作用。对于一个纯函数,我们如果可能会多次需要计算,最好是将其进行预处理,比如:质数筛、这些需要反复查询的结果。
|