F |LIS| = 3
https://atcoder.jp/contests/abc237/tasks/abc237_f
考虑用二分做最长上升子序列的数组的表示方法
\(f[i][j][k][l]表示从前i个选,长度为1的最长上升子序列中最小的数为j,长度为2的最长上升子序列中最后一个数最小的数为k,长度为3的最长上升子序列中最后一个数最小的数为l的方案数\)
由于可选的最大的数为\(m\),所以我们用\(m+1\)表示不存在的情况
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1010;
const int MOD = 998244353;
int n, m;
int f[1010][12][12][12];
signed main() {
cin >> n >> m;
f[0][m + 1][m + 1][m + 1] = 1;
for (int i = 1; i <= n; i ++ ) {
for (int j = 0; j <= m + 1; j ++ ) {
for (int k = j; k <= m + 1; k ++ ) {
for (int l = k; l <= m + 1; l ++ ) {
if (f[i - 1][j][k][l]) {
for (int x = 1; x <= m; x ++ ) {
vector<int> c(10);
c[1] = j, c[2] = k, c[3] = l, c[4] = m + 1;
int pos = 0;
for (int y = 1; y <= 3; y ++ )
if (c[y] != m + 1)
pos = y;
if (x > c[pos])
c[++ pos] = x;
else {
int p = 0;
for (int y = 1; y <= pos; y ++ )
if (x > c[y])
p = y;
c[p + 1] = x;
}
if (pos <= 3)
f[i][c[1]][c[2]][c[3]] = (f[i][c[1]][c[2]][c[3]] + f[i - 1][j][k][l]) % MOD;
}
}
}
}
}
}
int ans = 0;
for (int i = 1; i <= m; i ++ )
for (int j = i + 1; j <= m; j ++ )
for (int k = j + 1; k <= m; k ++ )
ans = (ans + f[n][i][j][k]) % MOD;
cout << ans << endl;
return 0;
}