题目大意

有 \(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. Java的HashMap是如何工作的?

    HashMap是一个针对数据结构的键值,每个键都会有相应的值,关键是识别这样的值. HashMap 基于 hashing 原理,我们通过 put ()和 get ()方法储存和获取对象.当我们将键值对 ...

  2. Excel之“提取指定符号(中括号)中的字符”

    提取A1中[]内的字符函数:=MID(A1,SEARCH("[",A1)+1,SEARCH("]",A1)-SEARCH("[",A1)-1 ...

  3. numpy计算数组中满足条件的个数

    Numpy计算数组中满足条件元素个数 需求:有一个非常大的数组比如1亿个数字,求出里面数字小于5000的数字数目 1. 使用numpy的random模块生成1亿个数字 2. 使用Python原生语法实 ...

  4. c、c++中-int型以float或者float型以int输出问题

    1.将浮点型以整形的类型输出问题 用VC6.0,会把以整形输出形式的浮点数输出为0: 1 #include"stdio.h" 2 int main() 3 { 4 float x= ...

  5. react开发教程(三)组件的构建

    什么是组件 组件化就好像我们的电脑装机一样,一个电脑由显示器.主板.内存.显卡.硬盘,键盘,鼠标.... 组件化开发有如下的好处:降低整个系统的耦合度,在保持接口不变的情况下,我们可以替换不同的组件快 ...

  6. c++实现状态模式

    实验:用Java代码模拟实现课堂上的"银行账户"的实例,要求编写客户端测试代码模拟用户存款和取款,注意账户对象状态和行为的变化. 由于是c++,不像java那么灵活,所以类的调用方 ...

  7. ccf201912-1 报数 C++代码实现

    代码实现: #include<iostream> using namespace std; /*题目限制为三位数*/ /*思路: 1.用一个长度为4的数组(初值为0)保存每个人分别跳过了几 ...

  8. 《头号玩家》AI电影调研报告(一)

    观<头号玩家>AI电影调研报告 一. 前言 有一部电影,上映开始就能让世界各不同年龄段.身处不同文化的人在一瞬间达到心意相通:其中的一些镜头,让影迷.游戏迷.ACG爱好者等拥有截然不同兴趣 ...

  9. SQLite 数据库使用记录

    SQLite 数据库使用记录 官网 https://www.sqlite.org/index.html 下载地址 https://www.sqlite.org/download.html 参考资料 S ...

  10. 帝国CMS只备份栏目和模板的方法

    方法一:不备份所有帝国cms数据内容表 我们知道帝国cms有8大模型,分别是 1.新闻系统数据表 ( phome_ecms_news )2.下载系统数据表 ( phome_ecms_download  ...