CF 1067A DP(算是数位DP? 算是第一道做出来的数位DP 嘻嘻)
题目链接:http://codeforces.com/contest/1067/problem/A
题意:
有一个长度为N的序列(2≤n≤1e5)满足:
a1≤a2,an≤an−1,ai≤max(ai−1,ai+1)
每一个ai的范围是[1,200]
求有多少种满足条件的序列
答案对998244353取模
dp[maxn][200][3] 根据每位与前一位关系转移
dp 第三维为0 表示 小于前一位
为1 表示 大于前一位
为2 表示 等于前一位
在转移过程中用前缀和来求区间和
因为空间不够 开滚动数组(其实dp数组也可以改成滚动,但是嫌麻烦就没改)
因为要取模,前缀和部分有可能减除负数,因此对答案加mod取模
#include<bits/stdc++.h>
#define mod 998244353
using namespace std;
long long dp[100005][205][3];
long long sum[2][205][3];
int a[100005];
int main(){
int n;
long long r=0;
int pre=0;
int now=1;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=200;i++){
dp[0][i][0]=1;
dp[0][i][1]=1;
dp[0][i][2]=1;
}
if(a[1]==-1){
for(int i=1;i<=200;i++){
dp[1][i][0]=0;
dp[1][i][1]=1;
dp[1][i][2]=0;
sum[pre][i][0]=0;
sum[pre][i][1]=sum[pre][i-1][1]+1;
sum[pre][i][2]=0;
}
}
else{
for(int i=1;i<=200;i++){
if(i==a[1]){
dp[1][i][0]=0;
dp[1][i][1]=1;
dp[1][i][2]=0;
sum[pre][i][0]=0;
sum[pre][i][1]=sum[pre][i-1][1]+1;
sum[pre][i][2]=0;
}
else{
dp[1][i][0]=0;
dp[1][i][1]=0;
dp[1][i][2]=0;
sum[pre][i][0]=0;
sum[pre][i][1]=sum[pre][i-1][1];
sum[pre][i][2]=0;
}
}
}
for(int i=2;i<n;i++){
for(int j=1;j<=200;j++){
if(a[i]==-1){
dp[i][j][0]=(sum[pre][200][0]-sum[pre][j][0]+sum[pre][200][2]-sum[pre][j][2])%mod;
dp[i][j][1]=(sum[pre][j-1][1]-sum[pre][0][1]+sum[pre][j-1][0]-sum[pre][0][0]+sum[pre][j-1][2]-sum[pre][0][2])%mod;
dp[i][j][2]=(dp[i-1][j][2]+dp[i-1][j][0]+dp[i-1][j][1])%mod;
sum[now][j][0]=(sum[now][j-1][0]+dp[i][j][0])%mod;
sum[now][j][1]=(sum[now][j-1][1]+dp[i][j][1])%mod;
sum[now][j][2]=(sum[now][j-1][2]+dp[i][j][2])%mod;
}
else{
if(j==a[i]){
dp[i][j][0]=(sum[pre][200][0]-sum[pre][j][0]+sum[pre][200][2]-sum[pre][j][2])%mod;
dp[i][j][1]=(sum[pre][j-1][1]-sum[pre][0][1]+sum[pre][j-1][0]-sum[pre][0][0]+sum[pre][j-1][2]-sum[pre][0][2])%mod;
dp[i][j][2]=(dp[i-1][j][2]+dp[i-1][j][0]+dp[i-1][j][1])%mod;
sum[now][j][0]=(sum[now][j-1][0]+dp[i][j][0])%mod;
sum[now][j][1]=(sum[now][j-1][1]+dp[i][j][1])%mod;
sum[now][j][2]=(sum[now][j-1][2]+dp[i][j][2])%mod;
}
else{
dp[i][j][0]=0;
dp[i][j][1]=0;
dp[i][j][2]=0;
sum[now][j][0]=sum[now][j-1][0];
sum[now][j][1]=sum[now][j-1][1];
sum[now][j][2]=sum[now][j-1][2];
}
}
}
for(int j=1;j<=200;j++){
sum[pre][j][0]=sum[now][j][0];
sum[pre][j][1]=sum[now][j][1];
sum[pre][j][2]=sum[now][j][2];
sum[now][j][0]=0;
sum[now][j][1]=0;
sum[now][j][2]=0;
}
}
if(a[n]==-1){
for(int i=1;i<=200;i++){
dp[n][i][0]=(sum[pre][200][0]-sum[pre][i][0]+sum[pre][200][2]-sum[pre][i][2])%mod;
dp[n][i][1]=0;
dp[n][i][2]=(dp[n-1][i][2]+dp[n-1][i][0]+dp[n-1][i][1])%mod;
}
}
else{
for(int i=1;i<=200;i++){
if(a[n]==i){
dp[n][i][1]=0;
dp[n][i][0]=(sum[pre][200][0]-sum[pre][i][0]+sum[pre][200][2]-sum[pre][i][2])%mod;
dp[n][i][2]=(dp[n-1][i][2]+dp[n-1][i][0]+dp[n-1][i][1])%mod;
}
else{
dp[n][i][1]=0;
dp[n][i][0]=0;
dp[n][i][2]=0;
}
}
}
for(int i=1;i<=200;i++){
r=(r+dp[n][i][0])%mod;
r=(r+dp[n][i][1])%mod;
r=(r+dp[n][i][2])%mod;
}
cout<<(r+mod)%mod<<endl;
}