题解:P12264『STA - R9』咏叹调调律
题意
对于一个字符集为 \(\{\tt A,B,C\}\) 的字符串,若其可通过不断删去其中的 \(\tt AB,CA,AAA,CCB\) 子序列将其删空,则称该串是好的。
给定常数 \(p,q,r\),对于一个好的串,若其中分别有 \(a,b,c\) 个 \(\tt A,B,C\),那么定义其权值为 \(p^aq^br^c\)。
给定正整数 \(n\),对于所有的 \(1\le k\le n\),求出所有长为 \(k\) 的好的串的权值和,对 \(998244353\) 取模。
\(n\le 500\)。
题解
首先观察字符 \(\tt A\),可以知道必定有一个前缀的 \(\tt A\) 匹配 \(\tt AB\)、一个后缀的 \(\tt A\) 匹配 \(\tt CA\)。如果我们可将 \(\tt AAA\) 划分为两部分,那么就可以变为一个前缀的 \(\tt A\) 匹配 \(\tt AB\) 或 \(\tt AAA\) 的前半部分,而剩余后缀中的 \(\tt A\) 匹配 \(\tt CA\) 或 \(\tt AAA\) 的后半部分,接下来将前缀 \(\tt A\) 与后缀 \(\tt A\) 分别记作 \(\tt A_L,A_R\)。
接下来是一个核心观察:将 \(\tt{{ A_L,C,A_R,B}}\) 分别看作两个左括号、一个左括号、一个右括号、两个右括号,则一次操作可删去的串为合法括号串。注意这只是必要条件,因为我们不能将两个左括号或右括号匹配不同类型的字符,如 \(\tt A_LA_RCB\) 是不合法的,我们只能通过括号匹配的思想进行性质推导。
由于替换后的括号串,其合法首先是一个必要条件,这也告诉我们如果一个字符串合法,其必定唯一对应一种替换 \(\tt A\) 为 \(\tt A_L,A_R\) 的方式。由于单括号的匹配自由度高于双括号的匹配自由度,故四种删除方式的优先级为 \(\tt A_LB>A_LA_RA_R/CCB>CA_R\)。
接下来开始考虑 DP。首先必须要记录当前的总长与字符 \(\tt A_L\) 与 \(\tt C\) 分别剩余的个数 \(i,j,k\) 三维,故接下来只能增加一些常数维度:
- 需要增加一维 \(0/1\) 表示当前的字符 \(\tt A\) 对应字符 \(\tt A_L\) 还是字符 \(\tt A_R\);
- 当出现字符 \(\tt A_R\) 时,我们优先考虑匹配 \(\tt A_LA_R\) 并等待下一个 \(\tt A_R\),但由于 \(\tt A_LB\) 的优先级高于 \(\tt A_LA_RA_R\),故如果当前可匹配 \(\tt CA_R\),需要预留一次反悔机会,增加一维 \(0/1/2\) 分别表示不存在 \(\tt A_LA_R\)/存在不可反悔的 \(\tt A_LA_R\)/存在可反悔的 \(\tt A_LA_R\) 即可。
当出现 \(\tt B\) 时,优先考虑与当前未配对的 \(\tt A_L\) 匹配,再考虑与当前可反悔的 \(\tt A_LA_R\) 进行匹配,最后尝试匹配 \(\tt CCB\);若存在已配对的 \(\tt A_LA_R\) 时再出现 \(\tt A_R\),那么必定将其匹配为 \(\tt A_LA_RA_R\),如果不这么做则此时必定存在两个 \(\tt C\),下次出现 \(\tt B\) 必定可匹配一组 \(\tt CCB\)。
直接枚举添加的字符类型做 DP 即可,时间复杂度 \(O(n^3)\)。
代码实现需要特别注意匹配顺序,不然就会出现 35 分笑传之错 Code B。
//f[i][j][k][0/1][0/1][0/1]:填了 i 位, 当前有 j 个可用 A_L, k 个 C, 是否切换至选择 A_R, 是否存在反悔机会, 是否已强制匹配 A_LA_R
int main(){
n=read(),p=read(),q=read(),r=read();
f[0][0][0][0][0][0]=1;
for(int i=0,t=1;i<n;i++,t^=1){
for(int j=0;j<=i;j++)
for(int k=0;j+k<=i;k++)
for(int a=0;a<2;a++)
for(int b=0;b<2;b++)
for(int c=0;c<2;c++){
int w=f[!t][j][k][a][b][c];
if(!w) continue;
int wa=1ll*w*p%mod,wb=1ll*w*q%mod,wc=1ll*w*r%mod;
//A_L
if(!a) inc(f[t][j+1][k][0][0][0],wa);
//A_R
if(c) inc(f[t][j][k][1][b][0],wa);
else if(b) inc(f[t][j][k+1][1][0][0],wa);
else if(j&&k) inc(f[t][j-1][k-1][1][1][0],wa);
else if(j) inc(f[t][j-1][k][1][0][1],wa);
else if(k) inc(f[t][j][k-1][1][0][0],wa);
//B
if(j) inc(f[t][j-1][k][a][b][c],wb);
else if(b) inc(f[t][j][k][1][0][c],wb);
else if(k>=2) inc(f[t][j][k-2][a][b][c],wb);
//C
inc(f[t][j][k+1][a][b][c],wc);
f[!t][j][k][a][b][c]=0;
}
for(int a=0;a<2;a++)
inc(ans[i+1],f[t][0][0][a][0][0]);
}
for(int i=1;i<=n;i++)
write(ans[i]),putc(' ');
flush();
}

浙公网安备 33010602011771号