「Codeforces 1067A」Array Without Local Maximums
      
      
    
   
  
  题目传送门
题意
给定长度为 \(n\) 的序列 \(a\),有些位置是 \(-1\),其余位置是 \(1\) 到 \(200\) 的一个整数。你需要在 \(-1\) 的位置填上\(1\) 到 \(200\) 的一个整数,使得序列 \(a\) 是好的。一个序列 \(a\) 是好的当且仅当满足以下三个条件:
- \(a_1\le a_2\)
 
- \(a_n\le a_{n-1}\)
 
- \(\forall i\in [2,n-1],a_i\le \max(a_{i-1},a_{i+1})\)
 
求方案数 \(\bmod 998244353\) 的值。
\(n\le 10^5\)
 题解
考虑 DP,\(dp_{i,j,0/1}\) 表示前 \(i\) 个数,\(a_i\) 为 \(j\),\(a_{i-1}< a_i\) / \(a_{i-1}\ge a_i\) 时的方案数。有转移
\[\begin{aligned} dp_{i,j,0}&=\sum_{k=1}^{j-1} dp_{i-1,k,0}+dp_{i-1,k,1}\\ dp_{i,j,1}&=dp_{i-1,j,0}+\sum_{k=j}^{200} dp_{i-1,k,1}\end{aligned}\]
可以发现这个式子可以用前缀和优化。
时间复杂度 \(O(nm)\),其中 \(m=200\)。
 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
   | #include <cstdio> #include <cctype> int read(){     register int x = 0;     register char f = 1, ch = getchar();     for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = !f;     for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ '0');     return f ? x : -x; } #define N 100005 #define P 998244353 int n, a[N], dp[N][205][2], pre[N][205][2]; int add(int x, int y){     return (x += y) >= P ? x - P : x; } int del(int x, int y){     return (x -= y) < 0 ? x + P : x; } int suf(int i, int j, int k){     return del(pre[i][200][k], pre[i][j - 1][k]); } int main(){     n = read();     for (register int i = 1; i <= n; ++i) a[i] = read();     for (register int i = 1; i <= 200; ++i){         if (a[1] == -1 || i == a[1]) dp[1][i][0] = 1;         pre[1][i][0] = add(pre[1][i - 1][0], dp[1][i][0]);     }     for (register int i = 2; i <= n; ++i)         for (register int j = 1; j <= 200; ++j){             if (a[i] == -1 || a[i] == j){                 dp[i][j][0] = add(pre[i - 1][j - 1][0], pre[i - 1][j - 1][1]);                 dp[i][j][1] = add(dp[i - 1][j][0], suf(i - 1, j, 1));             }             pre[i][j][0] = add(pre[i][j - 1][0], dp[i][j][0]);             pre[i][j][1] = add(pre[i][j - 1][1], dp[i][j][1]);         }     printf("%d\n", pre[n][200][1]); }
   |