D. MEX Sequences
题意:给定一个长度为
n
n
n 的序列,求MEX-correct子序列的个数。定义MEX-correct子序列为:对于数列的某一个子序列
x
1
,
x
2
,
…
,
x
k
x_{1}, x_{2}, \ldots, x_{k}
x1,x2,…,xk,任意
i
(
1
≤
i
≤
k
)
∣
x
i
−
MEX
(
x
1
,
x
2
,
…
,
x
i
)
∣
≤
1
i (1 \leq i \leq k)\left|x_{i}-\operatorname{MEX}\left(x_{1}, x_{2}, \ldots, x_{i}\right)\right| \leq 1
i(1≤i≤k)∣xi−MEX(x1,x2,…,xi)∣≤1。
思路:
状态定义:
dp[i][0] 表示 mex 值为i,最后一个元素为 i-1 的 MEX-correct子序列个数;
dp[i][1] 表示 mex 值为i,最后一个元素为 i+1 的 MEX-correct子序列个数。
状态转移:
假设有一个已经是 MEX-correct 的序列,现要在末尾添加一个元素 t,则将会有以下三种转移方式:
1.转移到 dp[t+1][0]
状态转移方程:dp[t+1][0]+=dp[t+1][0]+dp[t][0];
2.转移到 dp[t-1][1]
状态转移方程:dp[t-1][1]+=dp[t-1][1]+dp[t-1][0];
3.转移到 dp[t+1][1]
状态转移方程:dp[t+1][1]+=dp[t+1][1];
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e5+5;
const int mod=998244353;
int T,n,dp[N][2];
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>T;
while(T--){
cin>>n;
for(int i=0;i<=n+1;++i) dp[i][0]=dp[i][1]=0;
int t;
dp[0][0]=1;
for(int i=1;i<=n;++i) {
cin>>t;
dp[t+1][0]+=dp[t][0]+dp[t+1][0];
dp[t+1][0]%=mod;
if(t>=1) {
dp[t-1][1]+=dp[t-1][1]+dp[t-1][0];
dp[t-1][1]%=mod;
}
dp[t+1][1]+=dp[t+1][1];
dp[t+1][1]%=mod;
}
dp[0][0]-=1;
int ans=0;
for(int i=0;i<=n+1;++i) {
ans+=dp[i][0]+dp[i][1];
ans%=mod;
}
cout<<ans<<'\n';
}
}