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;
}
posted @ 2026-10-21 21:01  elon_giao  阅读(4)  评论(0)    收藏  举报