博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Codeforces Round #518 (Div. 2) [Thanks, Mail.Ru!](计数DP)
阅读量:384 次
发布时间:2019-03-05

本文共 973 字,大约阅读时间需要 3 分钟。

在这里插入图片描述
题意:有一个长度为n的序列,满足对于所有的a[x],与它相邻的两个元素a[x-1]和a[x+1]中至少有一个大于等于它,其中a[1]和a[n]当然只有一个相邻元素, 现在这个序列中有些数字被破坏了(标记为-1),问有多少种合法恢复方案(每个数字∈[1,200])
思路:dp[x][y][0/1/2]表示已经确定了第x个数字为y,且它左面那个数字a[x-1]小于/等于/大于它的总方案个数

#include
using namespace std;typedef long long ll;const int maxn=1e5+1;const ll mod=998244353;ll dp[maxn][201][3];int n,a[maxn];int main(){
scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i<=200;++i) if(a[1]==-1||a[1]==i) dp[1][i][0]=1; for(int i=2;i<=n;++i) {
for(int j=1;j<=200;++j) if(a[i]==-1||a[i]==j) dp[i][j][1]=(dp[i-1][j][0]+dp[i-1][j][1]+dp[i-1][j][2])%mod; ll sum=0; for(int j=1;j<=200;++j) {
if(a[i]==-1||a[i]==j) dp[i][j][0]=sum; sum=(sum+dp[i-1][j][0]+dp[i-1][j][1]+dp[i-1][j][2])%mod; } sum=0; for(int j=200;j>=1;--j) {
if(a[i]==-1||a[i]==j) dp[i][j][2]=sum; sum=(sum+dp[i-1][j][1]+dp[i-1][j][2])%mod; } } ll ans=0; for(int i=1;i<=200;++i) ans=(ans+dp[n][i][1]+dp[n][i][2])%mod; printf("%lld\n",ans);}

转载地址:http://vrewz.baihongyu.com/

你可能感兴趣的文章