Codeforces 1426F Number of Subsequences dp计数

题目链接
好久没打div3了 写虚拟场居然能AK了 挺简单的dp

给了我们一个字符串 含有abc 和? ?可以变化为a b c
问有多少个子序列是abc
由于? 会引出三个分支, 也就是说每多一个 ? 方案数就会扩大3^k
先考虑下不含有?的字符串如何对abc计数
令dp[flag][i] 表示在第i位 为flag种字符时 的贡献
那么 - - 害 直接搬我的英文题解上来 太懒了

We are given a string with the length of N, and the position containing “?” can be replaced by “a” or “B” or “C”. Finally, how many subsequences of “ABC” can be obtained, and the modulus of its number is 100000007

First of all, let’s consider the case that there is no “?” in the string. Define DP [s [J] — a '+ 1]] [J] to represent the contribution of the current character, and j to the position of the character in the string. For example, if the current character is “a”, then DP [1] [J] = (DP [1] [J-1] + pre [CNT])% mods The pre array represents the contribution to “a” after the replacement of “?, which is equivalent to the conversion of”? Into three branches. Similarly, for DP [2] [J] = (DP [2] [J-1] + DP [1] [J-1])% mods represents the contribution made by the previous “a” when the current character is “B”. Similarly, for the character “C”, since “?” produces three branches, we have to multiply the contribution of “?” by 3
94214264 Please give me some advice if there is something wrong

附代码

 #include<bits/stdc++.h>
#include<stdlib.h>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
 using namespace std;
 ll gcd(ll a,ll b){
    
    if(a<0)a=-a;if(b<0)b=-b;return b==0?a:gcd(b,a%b);}
template<typename T>void read(T &res){
    
    bool flag=false;char ch;while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
for(res=ch-48;isdigit(ch=getchar());res=(res<<1)+(res<<3)+ch - 48);flag&&(res=-res);}
ll lcm(ll a,ll b){
    
    return a*b/gcd(a,b);}
ll qp(ll a,ll b,ll mod){
    
    ll ans=1;if(b==0){
    
    return ans%mod;}while(b){
    
    if(b%2==1){
    
    b--;ans=ans*a%mod;}a=a*a%mod;b=b/2;}return ans%mod;}//快速幂%
ll qpn(ll a,ll b, ll p){
    
    ll ans = 1;a%=p;while(b){
    
    if(b&1){
    
    ans = (ans*a)%p;--b;}a =(a*a)%p;b >>= 1;}return ans%p;}//逆元   (分子*qp(分母,mod-2,mod))%mod;

ll dp[4][222222];
char s[222222];
ll pre[222222];
signed main(){
    
    
ll n;
read(n);
scanf("%s",s+1);
ll cnt=0;
pre[0]=1;
for(int i=1;i<=n;i++){
    
    
    pre[i]=pre[i-1]*3%mods; //处理3^k
}
for(int i=1;i<=n;i++){
    
    
for(int j=1;j<=3;j++){
    
    
  dp[j][i]=dp[j][i-1];
}
if(s[i]=='a'){
    
    
dp[1][i]=(dp[1][i-1]+pre[cnt])%mods;
}
if(s[i]=='b'){
    
    
dp[2][i]=(dp[2][i-1]+dp[1][i-1])%mods;
}
if(s[i]=='c'){
    
    
dp[3][i]=(dp[2][i-1]+dp[3][i-1])%mods;
}
if(s[i]=='?'){
    
    
dp[1][i]=(dp[1][i-1]*3+pre[cnt])%mods;
dp[2][i]=(dp[2][i-1]*3+dp[1][i-1])%mods;
dp[3][i]=(dp[2][i-1]+dp[3][i-1]*3)%mods;
cnt++;
}

}
printf("%lld\n",dp[3][n]%mods);


}
 

猜你喜欢

转载自blog.csdn.net/weixin_45948940/article/details/108920254
今日推荐