bzoj2958 序列染色

题目传送门

Description

  给出一个长度为N由B、W、X三种字符组成的字符串S,你需要把每一个X染成B或W中的一个。

  对于给出的K,问有多少种染色方式使得存在整数a,b,c,d使得:

  1<=a<=b<c<=d<=N

  Sa,Sa+1,...,Sb均为B

  Sc,Sc+1,...,Sd均为W

  其中b=a+K-1,d=c+K-1

  由于方法可能很多,因此只需要输出最后的答案对109+7取模的结果。

Input

  第一行两个正整数N,K

  第二行一个长度为N的字符串S

Output

  一行一个整数表示答案%(109+7)。

Sample Input

5 2

XXXXX

Sample Output

4

数据约定

  对于20%的数据,N<=20

  对于50%的数据,N<=2000

  对于100%的数据,1<=N<=106,1<=K<=106

Solution

  很容易想到N^2的做法(简单的DP)。

  f[i][j][h][s]——i表示到了第i个字符,状态为j(0表示没有k个B,1表示有k个B没有k个W,2表示既有k个B又有k个W),最后一位为h(0表示B,1表示W),最后一位有连续s个。

  具体转移就不说了。

  其实s是不用记的(F[i][j][h]),那怎么转移状态j呢?

  现有状态需要保证连续的B后有一个W,连续的W后有一个B,答案就是F[n+1][2][0],在第n+1为设为B,最后一位选B不会对答案有影响。

  假如第i位是B,F[i][j][0]=F[i-1][j][1]+F[i-1][j][0];(其他同理,先不考虑j)

  若第i-k+1位到第i位没有W(可以把所有的X变为B,使得有k个B),F[i][1][0]=F[i][1][0]+F[i-k][0][1];

  但依照第一条原则,F[i][0][0]是胡乱转移的,而从F[i-k][0][1]转移会有已经满足中间有k个B的情况,减掉重复的即可。F[i][0][0]=F[i][0][0]-F[i-k][0][1];

PS:DP神题,容斥大法好 残忍暴力水50。

CODE

#include<cstdio>
#include<algorithm> #define imax(a,b) ((a>b)?(a):(b)) typedef long long ll; using namespace std; typedef long long ll; const ll mods=1e9+7;
const int N=1000010;
int n,m,B[N],W[N];
ll F[N][3][2];
char st[N]; int main()
{
freopen("2237.in","r",stdin);
freopen("2237.out","w",stdout);
scanf("%d%d%s",&n,&m,st+1);
st[++n]='X';
for(int i=1;i<=n;i++)
{
B[i]=B[i-1]+(st[i]=='B');
W[i]=W[i-1]+(st[i]=='W');
}
F[0][0][1]=1ll;
for(int i=1;i<=n;i++)
{
if(st[i]!='W')
for(int j=0;j<3;j++) F[i][j][0]=(F[i-1][j][1]+F[i-1][j][0])%mods;
if(st[i]!='B')
for(int j=0;j<3;j++) F[i][j][1]=(F[i-1][j][1]+F[i-1][j][0])%mods;
if(i<m) continue;
if(st[i]!='W' && W[i]==W[i-m])
{
F[i][1][0]=(F[i][1][0]+F[i-m][0][1])%mods;
F[i][0][0]=(F[i][0][0]-F[i-m][0][1])%mods;
}
if(st[i]!='B' && B[i]==B[i-m])
{
F[i][2][1]=(F[i][2][1]+F[i-m][1][0])%mods;
F[i][1][1]=(F[i][1][1]-F[i-m][1][0])%mods;
}
}
printf("%lld\n",(F[n][2][0]+mods)%mods);
return 0;
}

最新文章

  1. 折腾Ubuntu下的android studio
  2. 免费 PSD 素材:25个全新的界面设计资源
  3. goLang文件遍历
  4. js 日期时间比较
  5. [改善Java代码]小心switch带来的空值异常
  6. 【原】iOS 获取当前和 前后n天的日期
  7. struts2,hibernate,spring整合笔记(1)
  8. TensorFlow深度学习笔记 循环神经网络实践
  9. [Python Study Notes]电池信息
  10. 【BZOJ1006】神奇的国度(弦图)
  11. Java并发编程(五)锁的使用(下)
  12. 第五周学习总结-HTML5
  13. python 3.6 + numpy + matplotlib + opencv + scipy 安装
  14. JS----贪吃蛇游戏
  15. Floyd模板(详细操作最基础版)
  16. python - while语句/pass/死循环/break/continue/while...else...
  17. 3个Activity间的切换
  18. 关于var关键字的详解
  19. Redis 过期时间
  20. 18. 使用模板【从零开始学Spring Boot】

热门文章

  1. C - Queue at the School
  2. Tomcat修改默认根目录
  3. 第6章 服务模式 在 .NET 中实现 Service Gateway(服务网关)
  4. 第5章分布式系统模式 使用客户端激活对象通过 .NET Remoting 实现 Broker
  5. RoIPooling与RoIAlign的区别
  6. 01--vim常用快捷键
  7. C#结束Explorer进程
  8. virtualenv 虚拟环境依赖安装
  9. Python爬虫2------爬虫屏蔽手段之代理服务器实战
  10. [luogu2272 ZJOI2007] 最大半连通子图 (tarjan缩点 拓扑排序 dp)