https://codeforces.com/contest/1426/problem/F
给出一个字符串,其中只包含 \(a,b,c,?\),其中 \(?\)可以换成 \(a,b,c\)中任意一个字母,问所有可能的序列中子序列 \(abc\) (可以不连续)的出现次数。
我们只需要扫一遍序列并同时维护 序列数量(遇到一个 \(?\) 序列数量变为 \(3\) 倍)、子序列 \(a\) 数量、子序列 \(ab\) 数量和子序列 \(abc\) 数量 这四个变量即可。
我们用 \(dp[0]\) 、\(dp[1]\) 、\(dp[2]\) 、\(dp[3]\) 分别表示序列数量、子序列 \(a\) 数量、子序列 \(ab\) 数量和子序列 \(abc\) 数量。
注意运算时取模
/*---------------------------------------------------------------
∧_∧
∧_∧ (′<_` )
( ′_ゝ`) / ⌒i
/ \ | |
/ / ̄ ̄ ̄ ̄/ |
__(__?つ/ _/ .| .|____
\/____/ (u ?
--------------------------------------------------------------*/
#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define req(i,a,b) for(int i=a;i>=b;i--)
#define pb push_back
#define fi first
#define se second
#define PI pair<int,int>
#define PII pair<ll,PI>
using namespace std;
typedef long long ll;
const int N = 2e5 + 7;
const ll mod = 1e9 + 7;
inline ll read(){
ll x=0;
int f=1;
char ch=getchar();
while(ch<‘0‘||ch>‘9‘){
if(ch==‘-‘)
f=-1;
ch=getchar();
}
while(ch>=‘0‘&&ch<=‘9‘){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
inline void print(ll x){
if(x<0)putchar(‘-‘),x=-x;
if(x>9)print(x/10);
putchar(x%10^48);
}
char s[N];
ll dp[4];
void slove(){
ll n;
n = read();
scanf("%s",s + 1);
dp[0] = 1;
for (int i = 1; i <= n; ++i)
{
if (s[i] == ‘a‘)
{
dp[1] = (dp[1] + dp[0]) % mod;
}else if(s[i] == ‘b‘){
dp[2] = (dp[2] + dp[1]) % mod;
}else if(s[i] == ‘c‘){
dp[3] = (dp[3] + dp[2]) % mod;
}else{
dp[3] = (3 * dp[3] % mod + dp[2]) % mod;
dp[2] = (3 * dp[2] % mod + dp[1]) % mod;
dp[1] = (3 * dp[1] % mod + dp[0]) % mod;
dp[0] = 3 * dp[0] % mod;
}
}
print(dp[3]);
puts("");
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("1.in", "r", stdin);
//freopen("1.out", "w", stdout);
#endif
int t = 1;
// t = read();
while(t--){
slove();
}
return 0;
}
``
F. Number of Subsequences(Codeforces Round #674 (Div. 3))
原文:https://www.cnblogs.com/KeepInCode/p/15092374.html