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 '\n' #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; }
前ICPC算法竞赛退役选手|现摸鱼ing