2019年8月30日CF群打卡题: 803A, 803B, 803C, 803D. 附加题: 803E, 803F.
803A Maximal Binary Matrix
描述
大意是给一个n
*n
的矩阵, 初始全是0
, 然后要求填充k
个1
, 并且填充完后的矩阵字典序最大(一行一行flatten之后的字典序) + 矩阵按对角线对称
思路
优先给第一行赋值, 因为要对称, 同时也给第一列赋值. 如果第一行完成后k
没有用完, 那么继续第二列. 需要注意的是, 如果当前剩余的k
是1
, 那么无法继续对称地赋值(除了顶点都是成对的), 此时需要另起一行(给下一个顶点).
代码
1 | def do(): |
803B Distances to Zero
描述
给一个数组nums
, 为每个数找离它最近(左或者右)的0
的距离. BFS水题, 一开始把所有0
的位置入队就行.
1 | import collections |
803C Maximal GCD
描述
给一个正整数n
, 要求输出一个长度为k
的严格递增数组, 这个数组满足:
- 所有元素之和是
n
. - 所有元素的最大公约数
(gcd)
最大.
如果找不到满足条件的数组, 返回-1
.
思路
假设目标数组所有元素最大公约数是gcd
, 因为元素之和是n
, gcd
必然也是n
的约数. 从gcd
最小的倍数(它本身)开始考虑, 如果能找到一个长度为k
单调递增的数列之和是n
那么满足条件.
所以问题转换为: 找到一个最大的gcd
使得gcd + gcd*2 + gcd*3 + ... + gcd*k <= n
. 如果和小于n
, 我们可以调整最后一项的大小(增大最后一项, 反正不会重复). 但是如果和大于n
, 因为这个和已经是我们能找到的最小的等差数列和了(对于长度为k
而言), 必然这个gcd
无解.
代码
1 | import math |
803D Magazine Ad
描述
结合了字符串处理和二分搜索的题. 给一个字符串ad
, 和一个我们能容忍的最大行数k
. 现在要给这个字符串分行, 当在容忍范围内时, 求一个最小的行宽(单行长度).
分行规则:
- 空格处可以分行
- 字符
-
处可以分行. 分出的本行带有这个-
- 其他情况不可以分行
思路
二分一下所有的行宽. 满足条件就继续缩小, 否则增大. 不过这个题不好写的是判断函数… 需要双指针记录当前的字符和上一个分割处的字符-
或者空格.
代码
1 | def do(): |
803E Roma and Poker
描述
原题在讲故事…总结成自己的语言大概是给一个字符串s
, 里面只有WDL?
四种字符. W
表示加1, L
表示减1, D
表示什么也不做, ?
表示这里可以是WDL
的任意一种.
初始值为0. 另一个输入值是k
. 要求重建字符串s
(也就是把所有不确定的?
确定化), 满足最终结果是k
或者-k
, 并且在字符串的中间任意一处结果不能是k
或者-k
.
思路
用一个dp
字典, dp[i]
表示在i
点可以收集到的所有(中间)值. 每次结合当前字符和dp[i-1]
确定此处的可能值. 如果k
和-k
没有出现在最后一个位置, 返回NO
. 否则可以反向重建(对于?
,根据右边的值,和当前的值推断?
代表什么).
(这个题也挺水的其实…还不如C题难)
代码
1 | import collections |
803F Coprime Subsequences
描述
给一个数组, 问这个数组里面, 有多少个序列subsequence
(下标不一样就算不同序列)满足: 这个序列的所有元素互质.
思路
所有元素互质意味这些元素的gcd
是1
. 我们可以枚举所有的因数, 每个因数对应着很多序列. 然后在总的序列数2**n - 1
(长度n
的序列有2**n - 1
个子序列)中减掉因数不是1
的那些.
上面的方法存在重复计数的问题: 对于因数2
的所有序列中, 包含了因数4
的. 所以对于2
的序列来说, 要减去4
, 6
, 8
…的数量. 容斥原理.
具体操作时需要逆序, 这样对于嵌套的重复部分, 不会多次减去.
代码
1 | import math |