Codeforces 1426F【Number of Subsequences】(dp)

CF dp2000分

题意:给你长度为n的字符串,其中有‘a’,'b','c','?'。其中'?'可以转变为a,b,c任意一个,问形成abc的子序列的最多数量?

解法:我认为这是一个很不错的dp问题,首先我们可以考虑单纯的无‘?’情况下的dp:

     其中dp[i][1]表示当前情况下a的数量。那么对于1可知,其dp[i][1]就等于其前缀和1的个数

     其中dp[i][2]表示当前情况下ab的数量。dp[i][2]=dp[i-1][2]+dp[i][1]

     其中dp[i][3]表示当前情况下abc的数量。dp[i][3]=dp[i-1][3]+dp[i][2]

     除此之外,因为会有'?'的出现,我们可以知道每增加一个'?',那么你的序列数量就会*3。所以对于‘?’的情况,举个例子吧,我们要处理‘a’的数量,那么就是前面多少个序列全部堆起来,再加前面序列数/3,即可得到当前情况下‘a’的数量,b,c同理

具体看代码吧,是一个top2日本选手的,我觉得比题解写得好

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '
'
#define eps 0.000000001
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
const int maxn=2e5+5;
ll dp[maxn][5];
int main(){
    int n;scanf("%d",&n);
    string s;cin>>s;s=" "+s;
    dp[1][0]=1;
    rep(i,1,n){
        rep(j,0,3) dp[i+1][j]=dp[i][j];
        if(s[i]=='a'){
            dp[i+1][1]+=dp[i][0];
            dp[i+1][1]%=mod;
        }
        if(s[i]=='b'){
            dp[i+1][2]+=dp[i][1];
            dp[i+1][2]%=mod;
        }
        if(s[i]=='c'){
            dp[i+1][3]+=dp[i][2];
            dp[i+1][3]%=mod;
        }
        if(s[i]=='?'){
            dp[i+1][0]=dp[i][0]*3;
            dp[i+1][0]%=mod;
            dp[i+1][1]=dp[i][1]*3+dp[i][0];
            dp[i+1][1]%=mod;
            dp[i+1][2]=dp[i][2]*3+dp[i][1];
            dp[i+1][2]%=mod;
            dp[i+1][3]=dp[i][3]*3+dp[i][2];
            dp[i+1][3]%=mod;
        }
    }
    cout<<dp[n+1][3]<<endl;
}
View Code
原文地址:https://www.cnblogs.com/Anonytt/p/13748312.html