对于一个字符串$s$,考虑构造一个等价的序列$a_{i}$,使得可以通过$a_{i}$来判定$s$是否合法

由于当一个w被改变后不会再变回来,因此可以把w的地方断开,分为若干段,两个段是独立的,即变为了若干个仅含有r和b的段

对于每一个段,令$a_{i}$为其中b的段数+1(序列$a_{i}$的长度即为总段数),其具有以下性质:

1.不存在长度小于$a_{i}$的操作序列可以得到该段

2.长为$a_{i}$的操作序列合法当且仅当以rb(若$a_{i}=1$则必须为r)开头

对于性质1,每一次操作至多让b的段数增加1,同时第1次操作无法增加,因此至少需要$a_{i}$次操作

对于性质2,首先$a_{i}\le 2$时成立,然后归纳,对于新加入的一段b,如果新加入的操作是b直接覆盖即可,否则令上一次b操作的范围增大,用r将其断开即可

然后如果不以rb开头,那么前两次操作不能使b的段数为1,类似结论1可得其无解

根据这两个结论,$a_{i}$符合我们构造的条件,考虑枚举$a_{i}$,枚举方法如下:

由于$a_{i}$为段数+1,因此该段长度$\le \max(2a_{i}-3,1)$,将所有段累加,又因为至少存在$m-1$个w的空隙($m$为段数),总长不超过$n$,即$\sum_{i=1}^{m}\max(2a_{i}-3,1)+m-1\le n$

令$a'_{i}=\max(a_{i},2)-1$,有$\max(2a_{i}-3,1)=2a'_{i}-1$,代入化简可得$\sum_{i=1}^{m}a'_{i}\le \lfloor\frac{n+1}{2}\rfloor$

当$n=70$,$a'_{i}$的方案数为81156种,再枚举$a_{i}=1$的数字个数,总共有418662种(计算代码如下)

[atARC089F]ColoringBalls_#define[atARC089F]ColoringBalls_#define_02
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 105
 4 int n,ans,f[N][N];
 5 int main(){
 6     n=35;
 7     f[0][0]=1;
 8     for(int i=1;i<=n;i++)
 9         for(int j=1;j<=i;j++)f[i][j]=f[i-j][min(i-j,j)]+f[i][j-1];
10     for(int i=1;i<=n;i++)f[i][i]+=f[i-1][i-1];
11     for(int i=0;i<=n;i++)ans+=f[i][i];
12     printf("%d",ans);
13 } 
View Code

对于一个$a_{i}$,我们要做两件事情:1.判定其是否合法;2.求出其对应的$s$数量

判定合法:贪心,优先操作$a_{i}$较大的,不断找到下一个r和b,随便统计一下即可

求方案数:先确定$a_{i}$的顺序,即将$a_{i}$打乱后不同的序列数,有$\frac{m!}{\prod_{i}(\sum_{j=1}^{n}[a_{j}=i])!}$种

将$s$的连续段缩为1个字母(记作$s'$),那么$s'$必然包含一个长为$l_{1}=2\sum_{i=1}^{m}a'_{i}-1$的子序列(即尽量短的方案),同时自身也是一个长为$l_{2}=2\sum_{i=1}^{m}a_{i}+1$的序列的子序列(即$l_{1}$补上两端的r和w)

一个例子:对于$a_{i}=\{2,1,3\}$,$l_{1}$为bwrwbrb,$l_{2}$为**wr**b**r**wrw**r**brb**rw**(其中加粗的为补上的r和w)

然后$s$可以看作插板法划分为$l_{2}$段,其中有$l_{2}-l_{1}$段可以为空,即有$n+(l_{2}-l_{1})-1\choose l_{2}-1$种

总时间复杂度为$o(418662n)$,可以通过

[atARC089F]ColoringBalls_#define[atARC089F]ColoringBalls_#define_02
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 205
 4 #define mod 1000000007
 5 pair<int,int>pos[N];
 6 int n,k,ans,a[N],sum[N],fac[N],inv[N];
 7 char s[N];
 8 void init(){
 9     fac[0]=inv[0]=inv[1]=1;
10     for(int i=1;i<N-4;i++)fac[i]=1LL*fac[i-1]*i%mod;
11     for(int i=2;i<N-4;i++)inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
12     for(int i=1;i<N-4;i++)inv[i]=1LL*inv[i-1]*inv[i]%mod;
13 }
14 int c(int n,int m){
15     return 1LL*fac[n]*inv[m]%mod*inv[n-m]%mod;
16 }
17 int calc(int m){
18     if (pos[m].first==k)return 0;
19     int s=0;
20     for(int i=0;i<k;i++)sum[i]=1;
21     for(int i=m;i;i--){
22         if ((a[m-i+1])&&(pos[i].second==k))return 0;
23         sum[pos[i].first]--;
24         sum[pos[i].second]-=a[m-i+1];
25     }
26     for(int i=k-1;i>=0;i--){
27         sum[i]+=sum[i+1];
28         if (sum[i]<0)return 0;
29     }
30     s=fac[m];
31     for(int i=1,j=1;i<=m;i=j){
32         while ((j<=m)&&(a[i]==a[j]))j++;
33         s=1LL*s*inv[j-i]%mod;
34     }
35     int l1=0,l2=0;
36     for(int i=1;i<=m;i++)l1+=max(a[i],1);
37     l1=l1*2-1;
38     for(int i=1;i<=m;i++)l2+=a[i]+1;
39     l2=l2*2+1;
40     return 1LL*c(n+(l2-l1)-1,l2-1)*s%mod;
41 }
42 void dfs(int k,int las,int s){
43     ans=(ans+calc(k-1))%mod;
44     for(int i=1;i<k;i++)
45         if (a[i]==1){
46             a[i]=0;
47             ans=(ans+calc(k-1))%mod;
48         }
49     for(int i=1;i<k;i++)
50         if (!a[i])a[i]=1;
51     for(a[k]=las;a[k]<=s;a[k]++)dfs(k+1,a[k],s-a[k]);
52 }
53 int main(){
54     init();
55     scanf("%d%d%s",&n,&k,s);
56     for(int i=1,x=0,y=0;i<=n;i++){
57         while ((x<k)&&(s[x]=='b'))x++;
58         y=max(x,y);
59         while ((y<k)&&(s[y]=='r'))y++;
60         pos[i]=make_pair(x,y);
61         if (x<k)x++;
62         if (y<k)y++; 
63     }
64     dfs(1,1,(n+1)/2);
65     printf("%d",ans);
66 }
View Code