ARC131F ARC Stamp
ARC131F ARC Stamp
题面
一个由 A,R,C 三种字符构成的字符串,你可以进行不超过 \(k\) 次操作:选择一个段长度 \(3\) 的子串改为 ARC。
思路
想到一段连续的形状应该是一个互相覆盖的波浪,也就是形如:

因为如果不是互相覆盖的就可以视为独立的两段。
那么我们就可以设 \(dp_{i,j,0/1/2}\) 表示在 \(i\) 前缀中用了 \(j\) 次操作的方案数,同时当前的结尾是:刚好结束/必需要后面的覆盖/帮后面覆盖。同时要注意:如果是刚好结束或者将被覆盖则原串不能与当前重复,即贡献为 \(3^{len}-1\);否则就是因为覆盖了两层所以原串可以使任何字符,贡献为 \(3^{len}\)。代码实现时细节较多,不同结尾具体的转移:
A意味着后面必须有东西覆盖它,可以帮前面的覆盖。从1,0转移至1。AR与上一个同理,区别在于长度。R意味着这是卡在中间的,即前后都需要被覆盖。从2转移至1。ARC意味着完美!可以帮前后覆盖或任意。0,1转移至0,2。RC意味着前面需要被覆盖,同时可以帮后面覆盖。从2转移至0,2。C与上一个同理,区别在于长度。
要注意判断的顺序,就比如结尾 C 被 ARC 是包含的。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define freop(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
#define endl '\n'
#define inf 0x7f7f7f7f
#define lb(x) ((x)&-(x))
#define pii pair<int,int>
#define fir first
#define sec second
#define mkp(a,b) make_pair(a,b)
const int N=5010,mod=998244353;
string s;
int n,k;
ll dp[N][N][3]={{{1}}},ans;
int main(){
cin.tie(0)->ios::sync_with_stdio(false);
cout.tie(0);
// freop();
//↑以上为初始化↑
//------------------------------
cin >> s >> k,k=min(k,n=s.size()),s="s"+s;
for(int i = 1;i<=n;++i){
for(int j = 0;j<=k;++j) //任意字符都可以理解为原串就有的,所以这是一类结尾的方案
//也可以理解为状态0是用来继承不同段答案的,也就是中间多余的转移不会影响后续答案
dp[i][j][0]=dp[i-1][j][0];
for(int j = 1;j<=k;++j)//注意if的顺序
if(s[i]=='A')//结尾是A就必须后面有东西覆盖它;可以帮前面的覆盖或自己作为开头。
dp[i][j][1]=(dp[i][j][1]+dp[i-1][j-1][0]*2+dp[i-1][j-1][1]*3)%mod;
else if(s[i-1]=='A'&&s[i]=='R')//与上一个同理。
dp[i][j][1]=(dp[i][j][1]+dp[i-2][j-1][0]*8+dp[i-2][j-1][1]*9)%mod;
else if(s[i]=='R')//以R结尾,意味着这是一个卡在中间的地方;必须要被前面覆盖且需要覆盖
dp[i][j][1]=(dp[i][j][1]+dp[i-1][j-1][2]*2)%mod;
else if(i>2&&s[i-2]=='A'&&s[i-1]=='R'&&s[i]=='C')//ARC可以作为结束或者帮后面档;可以接刚刚好或者帮前面档
dp[i][j][0]=(dp[i][j][0]+dp[i-3][j-1][0]*26+dp[i-3][j-1][1]*27)%mod,
dp[i][j][2]=(dp[i][j][2]+dp[i-3][j-1][0]*27+dp[i-3][j-1][1]*27)%mod;
else if(s[i-1]=='R'&&s[i]=='C')//与ARC同理;他必须被遮挡
dp[i][j][0]=(dp[i][j][0]+dp[i-2][j-1][2]*8)%mod,
dp[i][j][2]=(dp[i][j][2]+dp[i-2][j-1][2]*9)%mod;
else if(s[i]=='C')//与上一个同理
dp[i][j][0]=(dp[i][j][0]+dp[i-1][j-1][2]*2)%mod,
dp[i][j][2]=(dp[i][j][2]+dp[i-1][j-1][2]*3)%mod;
}
for(int i = 0;i<=k;++i) ans=(ans+dp[n][i][0])%mod;
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号