2021牛客多校第五场复盘
条评论前言
之前打完网络赛,麻了,停更了一会…
正在顺便考虑重新组队…前队友准备弃暗(ACM)投明(Offer)了…
然后29号和30号肝了个新生赛题目(原题大赛),不过好像有点难了…
复盘
B - Boxes
刚看的时候,以为是期望$DP$,仔细推了一下,发现貌似并不需要写比较复杂的$DP$。
因为在取到某一个盒子时,是否需要再取的概率是可以轻易计算出来的(由题意,剩下部分同色则停止,则概率为$P=1-2 * (\frac{1}{2})^k$)。
接着,题目要求代价最小,只需要排个序就可以了,因为代价大小和颜色这些变量是独立的。
对于花费代价获得提示的情况,可以设$dp[i]$的意义是已经打开了$i$个箱子时就结束,所需的最小数学期望是多少。然后我们逆序从结束的情况(是否需要打开第$n-1$个箱子)到只打开一个箱子时(只有初始完全同色才一个箱子都不需要打开),按照$P[i] \times C[i]$的方式推导即可。
1 | / * vegetable1024 | liushan.site | Maybe Lovely? * / |
D - Double Strings
首先这个题面看起来非常的劝退。
仔细读一下后,发现大概是要做这几件事:
- 在$A=(1,2,\dots,|A|)$和$B=(1,2,\dots,|B|)$中分别选取一个子序列$a,b$
- 子序列$a,b$的长度要相等,即$|a|=|b|$
- 在子序列$a$中存在一个位置$pos$,其$A_{a_{pos} } < B_{b_{pos} }$
- 对于$1,2,\dots,pos-1$这些位置,均有$A_{a_{i} } == B_{b_{i} }$
人话:
在$A$中选一个长度为$len$的子序列,$B$中选一个长度为$len$的子序列,要保证前$k-1$位相等,第$k$位满足$A_k<B_k$,其余位置随意,求选取方案数$mod \ 10^9+7$的结果。
观察数据范围,猜测复杂度大概是$O(n^2)$的。
然后开始分拆问题。
对于 相等 的情况,我们可以设$dp[i][j]$是在字符串$A$中$[1, i]$中选择,在字符串$B$中$[1,j]$中选择的 公共子序列 相等的 方案数 。
这貌似是一个很经典的$DP$(
- 如果$A[i]$和$B[j]$不相等,$dp[i][j]=dp[i][j-1]+dp[i-1][j]-dp[i-1][j-1]$
- 如果$A[i]$和$B[j]$相等,$dp[i][j]=dp[i][j-1]+dp[i-1][j]-dp[i-1][j-1] + dp[i - 1][j - 1] + 1$
- 其中,$+ dp[i - 1][j - 1] + 1$代表$A[i]$和$B[j]$自己组成一个子序列的方案数,以及与$[1, i-1]$和$[1, j-1]$中的公共子序列相接得到的子序列的方案数。
而后,我们需要比较$A[i+1]$和$B[j+1]$是否满足$A[i + 1] < B[j+1]$。
最后,我们需要得到,在字符串$A$的后半部分$[i+2,A_{len}]$和字符串$B$的后半部分$[j+2, B_{len}]$中,有多少种不同的选择方案,使得最后得到的子序列$a,b$长度相等。
在前面两个情况中,我们得到的子序列$a,b$的长度都是相同的。也就是说,对于最后一种情况,我们要枚举长度为$1,2,3,\dots$的选择方案。
更准确的,设完成了前两种情况的选择后,字符串$A$的后半部分长度为$len1$,字符串$B$的后半部分长度为$len2$,我们需要求出:
我们可以等价一下,由组合数定义,上面的式子可以转化为:
此时,问题其实等价于:在一个有$len1+len2$个球的盒子中取出$min ( len1, len2 ) $个球的方案数的和。
式子的意义转为:
- $C_{len1}^0 * C_{len2} ^ { min(len1, len2) } \rightarrow $ 在取出的$ min(len1,len2) $个球中,有$0$个球在前$len1$个球中被取出,有$min( len1, len2 )$个球在后$len2$个球中被取出。
- $C_{len1}^1 * C_{len2} ^ { min ( len1, len2 ) - 1}\rightarrow$ 在取出的$min(len1,len2)$个球中,有$1$个球在前$len1$个球中被取出,有$min{ (len1,len2) - 1}$个球在后$len2$个球中被取出。
- …
由此即可推导得到:
由于$len1+len2 \leq 10^4$,因此使用杨辉三角递推会导致空间过大。我们考虑通过递推阶乘逆元来计算组合数。
到此这道题就解决了。
1 | / * vegetable1024 | liushan.site | Maybe Lovely? * / |
H - Holding Two
构造题,第一次读题读错了送了一发,第二次就好了。
题意是构造一个矩阵,使得在某一方向上(横,竖,斜),不能有连续三个元素是相同的。
只需要:
1 | 0011001100110011 |
这样构造即可。
1 | / * vegetable1024 | liushan.site | Maybe Lovely? * / |
J - Jewels
$KM$模板题,最开始时候想过反悔贪心,但是好像搞不出来(
1 | / * vegetable1024 | liushan.site | Maybe Lovely? * / |
K - King of Range
单调队列+双指针。
最开始的时候想的是做一个$ST$表,枚举左端点,二分右端点,寻找最大值减去最小值满足题意的最大区间,然后再套一个主席树上去做区间第$k$大,统计有多少个答案。
撇开时间复杂度不说,这个做法本来也是有漏洞的。因为只需要区间内存在一对最大值减去最小值满足题意的数,其拓展得到的区间也是一定满足条件的。而区间第$k$大会漏掉一些情况无法统计。
错误代码:
1 | / * vegetable1024 | liushan.site | Maybe Lovely? * / |
而后我们考虑使用单调队列维护区间最值,双指针维护当前的区间。
- 当最大值减去最小值满足题意时,当前区间对答案的贡献就是$n - r + 1$,移动左指针,缩小区间。
- 否则,移动右指针,扩大区间。
由此即可完成该题。
1 | / * vegetable1024 | liushan.site | Maybe Lovely? * / |