[ARC089D] ColoringBalls

题面

ARC089D

题解

神仙题
一般对于这种干了一堆操作之后问最后能够得到多少种本质不同的序列的题目, 一般是枚举最后的序列然后去 check 他的合法性, 在 check 的过程中可以一顿乱搞, 反正怎么优秀怎么来

那么我们考虑 check 这个答案序列的合法性
把这个序列中白球看做 W , 红球看做 R , 篮球看做 B
然后得到的序列就一定是由这三个字母组成的
把他相同的缩成一坨, 那么最后得到的一定是形如 RBRBWBRBWBRWRBRWR 之类的
以 W 为分割点割开, 将其按照子段中 B 的个数分组, 有 (x) 个 B 就分到 (x + 1)
那么每个组就是这样的

  • 1 : R
  • 2 : B BR RB RBR
  • 3 : BRB RBRB BRBR RBRBR

等等, 对应的操作序列则为

  • 1 : r
  • 2 : rb
  • 3 : rb?

? 为通配符, 证明的话考虑归纳, 比较简单就不证了

我们把一个答案序列中的所有组的编号从大到小排序, 那么上面那个例子就是 3 3 2 2 1 , 记这个序列为 f

那么对于 f 相同的答案序列我们可以看做相同的

考虑到本质不同的 f 其实就相当于整数划分之类的, 因为 (n) 很小, 所以本质不同的 (f) 不会很多
那么我们就可以枚举 f , 考虑其是否合法, 然后计数

先考虑其是否合法, 考虑贪心

考虑按编号从大往小匹配, 从左往右扫, 每扫到一个 r 就将其加入队列(如果 f 中的组都匹配完了就不用加进去了), 每扫到一个 b 就将其与队首匹配并弹出队首, 然后将需要的通配符数量 (a_i) 记在这个 b 上, 再从右往左扫, 每扫到一个被匹配的 b 就看一下当前可以作为通配符的字符是否多于 (a_i)

我们保证编号大的组一定先匹配, 也就是后面的通配符数量会更多, 然后能匹配就匹配, 这样子显然是最优的

这样子我们就可以知道是否合法了

在考虑计数, 首先乘上一个可重排

那么接下来我们只用考虑 f 递减的情况即可

继续沿用上面的例子, f 为 3, 3, 2, 2, 1 时, 答案序列一定有 BRBWBRBWBWBWR 这样的子序列, 将这个子序列抠出来后, 把剩下的序列 unique , 一定是 WRBRBRWRBRBRWRBRWRBRWRW 的子序列, 设第一个子序列长度为 (l) , 第二个子序列长度为 (r) , 那么最后的方案数即为 (inom{n-l+r-1}{r-1})
即先强制第一个序列每个数都选一个, 然后将剩下的数分到这么多个集合里去, 集合大小可以为 0 , 直接插板就搞定了

Code

原文地址:https://www.cnblogs.com/ztlztl/p/13949629.html