zoukankan      html  css  js  c++  java
  • [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
    由于方法可能很多,因此只需要输出最后的答案对10^9+7取模的结果。

    Input
    第一行两个正整数N,K
    第二行一个长度为N的字符串S
    1<=N<=10^6,1<=K<=10^6

    Output
    一行一个整数表示答案%(10^9+7)。

    Sample Input
    5 2
    XXXXX

    Sample Output
    4


    考虑dp,设(f[i][0/1/2][0/1])表示长度为(i),状态为0/1/2,最后一位为0/1('B'/'W')的方案数

    状态的话,0表示不存在长度为k的B,也不存在长度为k的W;1表示存在长度为k的B,但不存在长度为k的B;2表示既存在长度为k的B,也存在长度为k的W

    转移的话根据(s[i-k])(s[i])需要考虑容斥,具体细节可以看看代码

    /*problem from Wolfycz*/
    #include<cmath>
    #include<ctime>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int frd(){
    	int x=0,f=1; char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline int read(){
    	int x=0,f=1; char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-');
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e6,Mod=1e9+7;
    char s[N+10];
    int sw[N+10],sb[N+10];
    int f[N+10][3][2];
    int updata(int x,int y,int z){
    	int tmp=(x+y)%Mod+z;
    	if (tmp<0)	tmp+=Mod;
    	return tmp%Mod;
    }
    int main(){
    	int n=read(),k=read();
    	scanf("%s",s+1);
    	for (int i=1;i<=n;i++){
    		sw[i]=sw[i-1],sb[i]=sb[i-1];
    		if (s[i]=='W')	sw[i]++;
    		if (s[i]=='B')	sb[i]++;
    	}
    	f[0][0][1]=1;
    	for (int i=1;i<=n;i++){
    		if (s[i]!='W'){
    			int tmp=(i>=k&&s[i-k]!='B'&&sw[i]==sw[i-k])?f[i-k][0][1]:0;
    			f[i][0][0]=updata(f[i-1][0][0],f[i-1][0][1],-tmp);
    			f[i][1][0]=updata(f[i-1][1][0],f[i-1][1][1], tmp);
    			f[i][2][0]=updata(f[i-1][2][0],f[i-1][2][1],   0);
    		}
    		if (s[i]!='B'){
    			int tmp=(i>=k&&s[i-k]!='W'&&sb[i]==sb[i-k])?f[i-k][1][0]:0;
    			f[i][0][1]=updata(f[i-1][0][0],f[i-1][0][1],   0);
    			f[i][1][1]=updata(f[i-1][1][0],f[i-1][1][1],-tmp);
    			f[i][2][1]=updata(f[i-1][2][0],f[i-1][2][1], tmp);
    		}
    	}
    	printf("%d
    ",(f[n][2][0]+f[n][2][1])%Mod);
    	return 0;
    }
    
  • 相关阅读:
    java:transient是什么,有什么作用
    如何阅读java源码
    java里面list是引用的好例子
    sort给文件按照大小排序
    HBase的rowkey排序和scan输出顺序
    记录一次事故——idea,sbt,scala
    一个简单的synchronized多线程问题、梳理与思考
    Android TextView文字描边的实现!!
    android中include标签的使用
    layout_weight 的解释及使用
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10021280.html
Copyright © 2011-2022 走看看