• 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 }
  • 相关阅读:
    变分法浅析
    再生核希尔伯特空间(RKHS)在监督学习(SVM)中的应用
    关于对偶最优化
    两个公式
    Linux系统——账号管理
    Linux系统——源码编译安装
    Linux系统——最小化安装
    Linux系统——本地yum仓库安装
    Linux系统——rpm命令
    Linux系统——vim编辑器
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7497293.html
Copyright © 2020-2023  润新知