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<=10^6,1<=K<=10^6

正解:$dp$。

神$dp$神状态系列,蒟蒻根本想不到。。

设$f[i][j][k]$表示当前搞到序列第$i$位,$j$为$0$表示没有连续$k$个$B$,$j$为$1$表示已经有连续$k$个$B$,但没有连续$k$个$W$,$j$为$2$表示有连续$k$个$B$和连续$k$个$W$,$k$为$0$表示这一位为$B$,$k$为$1$表示这一位为$W$。

直接转移,注意在能恰好产生$k$个$B$或$W$时,加上漏算的答案,减去重复的答案即可。

话说当时在$win7$下的$emacs$做这题有一个$W$写成$w$还看不出来。。

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define N (1000010)
 6 #define rhl (1000000007)
 7
 8 using namespace std;
 9
10 int f[N][3][2],sb[N],sw[N],n,k;
11 char s[N];
12
13 il void upd(RG int &v,RG int x,RG int y,RG int z){
14   v=x+y; if (v>=rhl) v-=rhl; v+=z;
15   if (v>=rhl) v-=rhl; return;
16 }
17
18 int main(){
19 #ifndef ONLINE_JUDGE
20   freopen("color.in","r",stdin);
21   freopen("color.out","w",stdout);
22 #endif
23   cin>>n>>k,scanf("%s",s+1);
24   for (RG int i=1;i<=n;++i){
25     sb[i]=sb[i-1],sw[i]=sw[i-1];
26     if (s[i]==‘B‘) ++sb[i];
27     if (s[i]==‘W‘) ++sw[i];
28   }
29   f[0][0][1]=1;
30   for (RG int i=1,tmp;i<=n;++i){
31     if (s[i]!=‘W‘){
32       if (i>=k && s[i-k]!=‘B‘ && sw[i]==sw[i-k]) tmp=f[i-k][0][1]; else tmp=0;
33       upd(f[i][0][0],f[i-1][0][0],f[i-1][0][1],rhl-tmp);
34       upd(f[i][1][0],f[i-1][1][0],f[i-1][1][1],tmp);
35       upd(f[i][2][0],f[i-1][2][0],f[i-1][2][1],0);
36     }
37     if (s[i]!=‘B‘){
38       if (i>=k && s[i-k]!=‘W‘ && sb[i]==sb[i-k]) tmp=f[i-k][1][0]; else tmp=0;
39       upd(f[i][0][1],f[i-1][0][0],f[i-1][0][1],0);
40       upd(f[i][1][1],f[i-1][1][0],f[i-1][1][1],rhl-tmp);
41       upd(f[i][2][1],f[i-1][2][0],f[i-1][2][1],tmp);
42     }
43   }
44   cout<<(f[n][2][0]+f[n][2][1])%rhl; return 0;
45 }
时间: 2024-08-07 21:17:27

bzoj2958 序列染色的相关文章

【BZOJ】1006 神奇的国度

[解析]完美消除序列+染色 [Analysis] 由题知他们的关系构成一个弦图,所以求出完美消除序列一定是成立的. 先求出,然后根据序列来染色,尽可能染小的. 其实时间戳那里用个线段树+二分好像也不错,甚至树状数组都可以,因为元素的变化是单调的... 在此给出证明: 首先进行以下的定义: 团数:最大团的大小. 色数:染色最少用的颜色. ∵团中颜色要两两不同 ∴团数<=色数 ∵我们对序列的染色共染了t种颜色且这样的染色是合法的,但是暂时不能保证最少. ∴t>=色数. 又∵我们的染色方法是贪心的,

[BZOJ 3791] 作业 【DP】

题目链接:BZOJ - 3791 题目分析 一个性质:将一个序列染色 k 次,每次染连续的一段,最多将序列染成 2k-1 段不同的颜色. 那么就可以 DP 了,f[i][j][0|1] 表示到第 i 个位置,染了 j 段,当前这一段颜色为 0|1 的最大价值. f[i][][] 只与 f[i-1][][] 有关,第一维用滚动数组就可以了. 代码 #include <iostream> #include <cstdio> #include <cstring> #inclu

solution

DAY1 A  UVAlive 3937 painting the sticks 给你一些木棒,按照给定的颜色序列染色,每次最多可以染连续的3块(每块的颜色可以不一样),每块可以由任意多个连续木棒组成,求最少步数. 题目里有说不允许覆盖染色吗?统计不同的颜色块的个数,除以3并向上取整就是答案了.. B UValive3938 "Ray, Pass me the dishes!" 给一个长度为n的序列,有m个询问,每次询问某个区间内的和最大的子区间 线段树问题,对于线段树上的每个节点维护

计数类问题专题

主要是前两天被uoj的毛爷爷的题虐的不轻,心里很不爽啊,必须努力了,, 计数类问题分为:1.组合数学及数论计数 2.dp:状态压缩dp,插头轮廓线dp,树形dp,数位dp,普通dp 3.容斥原理 4.polya原理 5.图论计数 6.生成函数 7.其它(生成树计数等等) 本文主要研究前3个内容 考虑基本计数原理:加法原理,减法原理,乘法原理,除法原理 计数的基本原则:结果不重不漏 加法原理比较自然,中间过程有时减法原理 考虑到无向,有向图的各种量值(生成树之类)计数,状态压缩dp解决 论文:ht

国庆清北 数据结构

数据结构:树状数组,堆节点和左右儿子合并的线段树 树状数组:快速求前缀和,单点修改删东西,加东西,查询最小值,最大值lowbit(4)=4每个位置存一段区间的和二维树状数组???n*m的空间 线段树,动态开节点序列核心:区间可合并性借教室:区间减法,求区间最小值线段树一定可以1e5 ,维护少,域小可以过1e6最大子段和:支持区间赋值,常数时间内得到更新完的信息楼房重建:从头维护严格上升子序列,且支持可合并性一个区间起码维护从头开始子序列...左 右 右边怎么接起来? 并查集路径压缩后不能撤销(时

bzoj 1006: [HNOI2008]神奇的国度 弦图的染色问题&amp;&amp;弦图的完美消除序列

1006: [HNOI2008]神奇的国度 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1788  Solved: 775[Submit][Status] Description K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系等等的存在.所谓N边关系,是指N个人 A1A2...An之间仅存在N对认识关系:(A1A2)

【codevs1191】数轴染色 序列分块

题目大意: 长度为n的序列,开始时全都是黑色的,m次操作,每次把[l,r]变成白色,求每次操作后剩下的黑点数. 分块直接做. 设rest[i]表示第i块剩下的个数,p为每个点的装填. 对于[l,r],找到l,r所处的块lblock,rblock. 把lblock+1到rblock-1的块的rest赋为0,O(√n). 然后判断一下rest[lblock]是否空,如果不空则直接扫描更新rest和p,rblock同理. 注意这里要判断一下rest,因为整体赋值的时候p没有更新. 小结:对于分块,块数

BZOJ 2243:染色(树链剖分+区间合并线段树)

[SDOI2011]染色Description给定一棵有n个节点的无根树和m个操作,操作有2类:1.将节点a到节点b路径上所有点都染成颜色c:2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”.请你写一个程序依次完成这m个操作.Input第一行包含2个整数n和m,分别表示节点数和操作数:第二行包含n个正整数表示n个节点的初始颜色下面 行每行包含两个整数x和y,表示x和y之间有一条无向边.下面 行每行描述一个操作:“C

[BZOJ 1006] [HNOI2008] 神奇的国度 【弦图最小染色】

题目链接: BZOJ - 1006 题目分析 这道题是一个弦图最小染色数的裸的模型. 弦图的最小染色求法,先求出弦图的完美消除序列(MCS算法),再按照完美消除序列,从后向前倒着,给每个点染能染的最小颜色. 求出的颜色数就是最小染色,同时也是最大团. 代码 #include <iostream> #include <cstdlib> #include <cstdio> #include <cmath> #include <cstring> #in