https://www.luogu.org/problem/P3205
#include <bits/stdc++.h>
#define N 2001
#define MOD 19650827
using namespace std;
int n;
int a[N];
int f[N][N][2];
inline int read()
{
char ch = getchar();
int x = 0, f = 1;
while(ch > '9' || ch < '0')
{
if(ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
void Solve()
{
for(int i = 1; i <= n; i++)
f[i][i][0] = 1;
for(int l = 2; l <= n; l++)
{
for(int i = 1; i <= n - l + 1; i++)
{
int j = i + l - 1;
if(a[j] > a[j - 1])
f[i][j][1] += f[i][j - 1][1];
if(a[j] > a[i])
f[i][j][1] += f[i][j - 1][0];
if(a[i] < a[i + 1])
f[i][j][0] += f[i + 1][j][0];
if(a[i] < a[j])
f[i][j][0] += f[i + 1][j][1];
f[i][j][0] %= MOD;
f[i][j][1] %= MOD;
}
}
printf("%d", (f[1][n][0] + f[1][n][1]) % MOD);
}
int main()
{
n = read();
for(int i = 1; i <= n; i++)
a[i] = read();
Solve();
return 0;
}
f[ i ][ j ][ k ]为 i 到 j 这一段将 i 或 j 插入的情况数, k = 1 表示在右端插入, k = 0 在左端插入。
当右端点的数大于上一个且上一个插入在右端时:
f[ i ][ j ][ 1 ] += f[ i ][j - 1][ 1 ];
当右端点的数大于左端点且上一个插入在左端时:
f[ i ][ j ][ 1 ] += f[ i ][ j - 1 ][ 0 ];
当左端点的数小于后一个且上一个插入在左端时:
f[ i ][ j ][ 0 ] += f[ i + 1 ][ j ][ 0 ];
当左端点的数小于右端点且上一个插入在右端时:
f[ i ][ j ][ 0 ] += f[ i + 1 ][ j ][ 1 ];