AGC045C Range Set
简单题。
显然初始全零和全一没有区别,可以全部进行一次覆盖,所以如果 A>B 可以交换 A,B 。
首先可以发现,如果打算在结尾放 B 个 1 ,那么前面任意放的状态都可以被构造出来。因为总是可以用 A 个 0 去覆盖掉一部分的 1 。
接着考虑,会发现如果在序列中任意存在一段连续 B 个 1 ,那么它的左右的构造是互不影响的,都可以用一样的方法造出来。所以只要序列中存在一段连续 B 个 1 就一定可以构造出来。
如果序列中不存在连续 B 个 1 ,有时也是可以被构造出来的。可以发现,如果有一段长度大于等于 A 的 0 序列,它其实可以是在最后把这段从 1 变成 0 的,因此可以把它看成一段 1 。
如果顺着这个思路去想,可以发现对于一段连续的长度大于等于 B 的 1 ,其实也可以看作是在最后通过将一段 0 变成 1 得到的。所以如果倒着思考这个问题,只要存在一段长度大于等于 B 的 1 ,它总是可以交替进行变 0 和变 1 并且最终将整个序列回滚成 0 ,所以是一定可以被构造出来的。
所以倒着考虑,一个序列是否合法就变成了在开始时可以将长度大于等于 A 的连续 0 段变成 1 ,问是否可以造出一段长度大于等于 B 的连续 1 段。
显然,考虑反面更容易,考虑计数不可被构造出来的序列个数。也就是即使将所有大于等于 A 的 0 段反转成 1 ,也无法在序列中凑出一个长度大于等于 B 的段。也就是说任何两个长度小于 A 的 0 段的间隔必须小于 B 。这个问题可以简单地用 dp 解决。
设 dp[i][0/1] 表示当前考虑到序列的第 i 个位置,最后一段放的是长度小于 A 的 0 段还是长度小于 B 的 1+0 段,随便转移一下即可。
复杂度 O(n2) 。
cpp
1 |
|