题目大意

有 \(n\) 个白色的小球排成一排,有一个长为 \(k\) 的字符串 \(S\)。接下来进行 \(k\) 次操作。

第 \(i\) 个操作,选择一段连续的小球(可以为空),若 \(S\) 中第 \(i\) 个字符是 r,则将这些球染成红色;若是 b,则将它们染成蓝色。由于染料的特性,不能直接用蓝色来染白色。

求在进行完所有操作后,所有小球的颜色序列可以有多少种。

对 \(10^9+7\) 取模。

\(n,k\le 70\).

解题思路

首先,因为考虑按顺序进行染色操作的结果非常复杂,而且难以分辨重复状态,所以不妨考虑如何判断一个序列是否合法。

不妨假设整个序列有 \(m\) 个有色段,每段的蓝色段个数为 \(b_i\)。

显然对于 \(b_i=0\) 的段,只需要一个 r;而对于 \(b_i>1\) 的段,经过手玩不难发现,它需要一个 rb,以及 \(b_i-1\) 次任意染色。

所以假设我们已经有了 \(b\) 数组,不妨贪心地达成染色方案:

按照 \(b_i\) 的从大到小排序,首先尽量选最靠前的 r,然后对于 \(b_i>0\) 的,在选的 r 之后尽量选最靠前的 b,最后对于 \(b_i>1\) 的,选择 rb 后最靠前的 \(b_i-1\) 个操作。

因为 \(n\le 70\),可以用复杂度划分数相关的做法,那么不妨直接类似划分数枚举 \(b_i\) 的情况。

接下来对于已经确定的一组 \(b_i\) 如何求方案的思路,个人感觉比较妙 (从 xht37 那里学到的)。

以 \(b={1,2,2,3,4}\) 为例,首先是一个多重组合数 \(\binom{5}{1,2,1,1}\),然后是具体染色的方案数。

这个序列对应的染色序列一定包含子序列 R W B W B W BRB W BRBRB,也就是每个 \(b_i\) 的最短可能,长度为 \(15\)。

同时,其对应的染色序列一定是 W R W RBR W RBR W RBRBR W RBRBRBR W 的子序列,也就是每个 \(b_i\) 的最长可能,长度为 \(25\)。

而此时我们的染色序列是把相邻的同色球缩到一起,所以最终方案相当于把 \(n-15\) 个字符分成 \(25\) 组,每组可以为空的方案数。答案为 \(\binom{n-15+25-1}{25-1}\)。

#include <bits/stdc++.h>
#define lfor(x, y, z) for(int x(y), x##_end(z); x <= x##_end; ++x)
#define rfor(x, y, z) for(int x(y), x##_end(z); x >= x##_end; --x)
#define lep(x, y, z) for(int x(y), x##_end(z); x < x##_end; ++x)
#define ls(x) t[x].lc
#define rs(x) t[x].rc
#define LL long long
using namespace std; const int N(205), mod(1e9 + 7); int n, K; char ch[N];
int Ans;
int m, b[N];
int ban[N], loc[N];
int fac[N], ifac[N];
int div_cnt; template <typename T> inline void read(T &x){
x = 0; int f = 1, c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)) x = x * 10 + c - '0', c = getchar();
x *= f;
} inline int Mod(int x){ return x + ((x >> 31) & mod); }
inline void MOD(int &x){ x = x + ((x >> 31) & mod); }
inline int C(int n, int m){
if(n < m || m < 0) return 0;
return (LL) fac[n] * ifac[n - m] % mod * ifac[m] % mod;
}
inline int qpow(int x, int a = mod - 2){
int sum = 1;
while(a) sum = a & 1 ? (LL) sum * x % mod : sum, x = (LL) x * x % mod, a >>= 1;
return sum;
} void prep(int n = 200){
fac[0] = 1; lfor(i, 1, n) fac[i] = (LL) fac[i - 1] * i % mod;
ifac[n] = qpow(fac[n]); rfor(i, n - 1, 0) ifac[i] = (LL) ifac[i + 1] * (i + 1) % mod;
} bool legal(){
int now = 1, sum = m - 1; lfor(i, 1, K) ban[i] = 0;
lfor(i, 1, m) if(b[i]) sum += b[i] * 2 - 1; if(sum > n) return 0; rfor(i, m, 1){
while(now <= K && ch[now] != 'r') ++now;
if(now > K || ch[now] != 'r') return 0; loc[i] = now, ban[now] = 1, ++now;
} now = 1;
rfor(i, m, 1) if(b[i]){
now = max(now, loc[i] + 1);
while(now <= K && ch[now] != 'b') ++now;
if(now > K || ch[now] != 'b') return 0; loc[i] = now, ban[now] = 1, ++now;
} now = 1;
rfor(i, m, 1) if(b[i]){
int sum = b[i] - 1;
now = max(now, loc[i] + 1);
while(now <= K && sum) sum -= !ban[now], ++now;
if(sum) return 0;
}
return 1;
} inline int Calc(){
int sum = fac[m], p = 1;
lfor(i, 2, m) if(b[i] != b[p]) sum = (LL) sum * ifac[i - p] % mod, p = i;
return (LL) sum * ifac[m - p + 1] % mod;
}
void check(){
if(!legal()) return;
int A = m - 1, B = m + 1;
lfor(i, 1, m){
if(b[i] == 0) A += 1, B += 1;
else A += b[i] * 2 - 1, B += b[i] * 2 + 1;
}
int tmp = (LL) Calc() * C(n - A + B - 1, B - 1) % mod;
MOD(Ans += (LL) Calc() * C(n - A + B - 1, B - 1) % mod - mod);
}
void dfs(int R, int A, int L, int lst){
check();
++m;
for(int i = lst; R && i + 1 <= A && L + max(1, i * 2 - 1) <= n + 1; ++i)
b[m] = i, dfs(R - 1, A - 1 - i, L + max(1, i * 2 - 1), i);
--m;
} int main(){
read(n), read(K), prep();
scanf("%s", ch + 1); int cntr = 0, cntb = 0;
lfor(i, 1, K) if(ch[i] == 'r') ++cntr; else ++cntb; dfs(cntr, K + 1, 0, 0); cout << Ans << endl;
return 0;
}

[题解][ARC089D] ColoringBalls的更多相关文章

  1. 贪心/构造/DP 杂题选做Ⅲ

    颓!颓!颓!(bushi 前传: 贪心/构造/DP 杂题选做 贪心/构造/DP 杂题选做Ⅱ 51. CF758E Broken Tree 讲个笑话,这道题是 11.3 模拟赛的 T2,模拟赛里那道题的 ...

  2. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  3. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  4. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  5. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  6. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  7. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  8. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  9. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

随机推荐

  1. elasticsearch 索引数据多了怎么办,如何调优,部署 ?

    面试官:想了解大数据量的运维能力. 解答:索引数据的规划,应在前期做好规划,正所谓"设计先行,编码在后", 这样才能有效的避免突如其来的数据激增导致集群处理能力不足引发的线上客户 ...

  2. 说出 5 个 JDK 1.8 引入的新特性?

    Java 8 在 Java 历史上是一个开创新的版本,下面 JDK 8 中 5 个主要的特性: Lambda 表达式,允许像对象一样传递匿名函数 Stream API,充分利用现代多核 CPU,可以写 ...

  3. 数据分析之Numpy的基本操作

    Numpy NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库. 1 创建 ndarray 使 ...

  4. 学习Kvm(一)

     背景介绍 传统数据中心面临的问题: 资源使用率低 资源分配不均 自动化能力差 初始化成本高   云计算: 云计算是一种按使用量付费的模式,这种模式提供可用的.便捷的.按需的网络访问, 进入可配置的计 ...

  5. 洋桃电子之STM32

    1.ARM内核与分类 作者:知乎用户链接:https://www.zhihu.com/question/52915983/answer/258507276来源:知乎著作权归作者所有.商业转载请联系作者 ...

  6. 学习webpack前的准备工作

    前言 由于vue和react的流行,webpack这个模块化打包工具也已经成为热门.作为前端工程师这个需要不断更新自己技术库的职业,真的需要潜下心来学习一下. 准备工作(针对mac用户) 安装 hom ...

  7. 前端面试题整理——HTML/CSS

    如何理解语义化: 对应的内容是用相应意思的标签,增加开发者和机器爬虫对代码的可读性. 块状元素和内联元素: 块状元素有:display:block/table:有div h1 h2 table ul  ...

  8. python-筛法求素数

    [题目描述]用户输入整数n和m(1<n<m<1000),应用筛法求[n,m]范围内的所有素数. [练习要求]请给出源代码程序和运行测试结果,源代码程序要求添加必要的注释. [输入格式 ...

  9. 第二次课堂练习-连接hbase数据库-页面展示

    图片来源:中国知网 页面来源:中国科学院文献情报中心-科技查新平台 如有侵权,请评论留言

  10. mysql基本操作2

    ##DDL控制表结构,不支持事务##DML控制表数据,支持事务       DQL专门做查询  ##TCL 管理事务##DCL 管理数据库权限     ##ORDER BY  子句-根据指定列对结果集 ...