bzoj2958 & bzoj3269

来源:互联网 发布:做程序员需要什么条件 编辑:程序博客网 时间:2024/06/16 17:37

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

HINT

Source

 中国国家队清华集训 2012-2013 第一天

 

题解:

我的算法和网上别人的好像不太一样。。。

每次转移都是一段B或一段W,所以记dp[i][j][k]为算完i位,j=0,1,2表示没有完成B,没有完成W,BW都完成了,k表示上一个是B还是W。

普通的dp直接枚举从哪一位转移,长度大于k强制修改j。

时间复杂度O(n^2)。

看到转移是把一段dp求和,记录dp的前缀和即可。

时间复杂度O(n)。

 

 

#include <stdio.h>#include <algorithm> using namespace std; //long longconst int mod = 1000000007;const int maxn = 1200000;int n , k;char z[maxn];int dp[maxn][3][3] , last[maxn][3] , sum[maxn][3][3];void work () {    int i , j , l;    scanf ( "%d%d" , &n , &k );    scanf ( "%s" , z + 1 );    if ( k > n ) {        printf ( "0\n" );        return ;    }    j = n;    for ( i = n ; i >= 1 ; i-- ) {        if ( j > i ) j = i;        while ( j >= 0 && z[j] != 'W' ) j--;        last[i][1] = j;    }    j = n;    for ( i = n ; i >= 1 ; i-- ) {        if ( j > i ) j = i;        while ( j >= 0 && z[j] != 'B' ) j--;        last[i][2] = j;    }    //for ( i = 1 ; i <= n ; i++ ) printf ( "%d %d\n" , last[i][1] , last[i][2] );    //if ( z[1] != 'W' ) {    //  if ( k != 1 ) dp[1][0][1] = 1;    //  else dp[1][1][1] = 1;    //}    dp[0][0][1] = dp[0][0][2] = sum[0][0][1] = sum[0][0][2] = 1;    //if ( z[1] != 'B' ) dp[1][0][2] = 1;    //sum[1][0][1] = dp[1][0][1]; sum[1][1][1] = dp[1][1][1];    //sum[1][0][2] = dp[1][0][2];    for ( i = 1 ; i <= n ; i++ ) {        if ( last[i][2] <= i ) {            dp[i][0][2] += (sum[i-1][0][1] - (last[i][2]!=0?sum[last[i][2]-1][0][1]:0) + mod) % mod;            dp[i][0][2] %= mod;        }        l = i - 1 - k + 1;        if ( last[i][1] <= i ) {            if ( last[i][1] <= l ) {                dp[i][0][1] += (sum[i-1][0][2] - sum[l][0][2] + mod) % mod;                dp[i][0][1] %= mod;                dp[i][1][1] += (sum[l][0][2] - (last[i][1]!=0?sum[last[i][1]-1][0][2]:0) + mod) % mod;                dp[i][1][1] %= mod;            }            else {                dp[i][0][1] += (sum[i-1][0][2] - (last[i][1]!=0?sum[last[i][1]-1][0][2]:0) + mod) % mod;                dp[i][0][1] %= mod;            }        }        //printf ( "%d\n" , l );        /*  printf ( "%d %d %d %d\n" , dp[1][0][1] , dp[1][0][2] ,             (sum[i-1][0][1] - sum[last[i][2]-1][0][1]),            (sum[i-1][0][2] - sum[last[i][1]-1][0][2]) );*/        if ( last[i][2] <= i ) {            if ( last[i][2] <= l ) {                dp[i][1][2] += (sum[i-1][1][1] - sum[l][1][1] + mod) % mod;                dp[i][1][2] %= mod;                dp[i][2][2] += (sum[l][1][1] - (last[i][2]!=0?sum[last[i][2]-1][1][1]:0) + mod) % mod;                dp[i][2][2] %= mod;            }            else {                dp[i][1][2] += (sum[i-1][1][1] - (last[i][2]!=0?sum[last[i][2]-1][1][1]:0) + mod) % mod;                dp[i][1][2] %= mod;            }        }        if ( last[i][1] <= i ) {            dp[i][1][1] += (sum[i-1][1][2] - (last[i][1]!=0?sum[last[i][1]-1][1][2]:0) + mod) % mod;            dp[i][1][1] %= mod;        }        if ( last[i][2] <= i ) {            dp[i][2][2] += (sum[i-1][2][1] - (last[i][2]!=0?sum[last[i][2]-1][2][1]:0) + mod) % mod;            dp[i][2][2] %= mod;        }        if ( last[i][1] <= i ) {            dp[i][2][1] += (sum[i-1][2][2] - (last[i][1]!=0?sum[last[i][1]-1][2][2]:0) + mod) % mod;            dp[i][2][1] %= mod;        }        for ( j = 1 ; j <= 6 ; j++ ) sum[i][(j-1)/2][(j-1)%2+1] = (sum[i-1][(j-1)/2][(j-1)%2+1]+dp[i][(j-1)/2][(j-1)%2+1]) % mod;    }    //for ( i = 0 ; i <= n ; i++ ) printf ( "%d %d %d %d %d %d\n" , dp[i][0][1] , dp[i][0][2] , dp[i][1][1] , dp[i][1][2] , dp[i][2][1] , dp[i][2][2] );    //printf("\n");    //for ( i = 0 ; i <= n ; i++ ) printf ( "%d %d %d %d %d %d\n" , sum[i][0][1] , sum[i][0][2] , sum[i][1][1] , sum[i][1][2] , sum[i][2][1] ,sum[i][2][2] );    printf ( "%d\n" , ((dp[n][2][1] + dp[n][2][2]) % mod + mod ) % mod);}int main () {    //FILE *fpr = freopen ( "bzoj3269.in" , "r" , stdin );    //FILE *fpw = freopen ( "bzoj3269.out" , "w" , stdout );    work ();    return 0;}


 

0 0
原创粉丝点击