abc237 F - |LIS| = 3
题意:
求长度为 \(n\),值域为 \([1,m]\),最长严格上升子列的长度恰为 \(3\) 的数组个数
\(3\le n\le 1000, 3\le m\le 10\)
思路:
考虑二分贪心 \(O(nlogn)\) 求 LIS 的过程:\(g_l\) 表示长度为 \(l\) 的 LIS 的最小末尾值,遍历到 \(a_i\) 时找一合适 \(g_j\) 更新之。也就是说更新依赖于数组 \(g\)
这题 LIS 长度不超过 \(3\),可以把每时每刻的整个数组 \(g\) 记录下来:f[i][g1][g2][g3] 表示考虑前 \(i\) 个元素,当前的 \(g[] = \{g1,g2,g3\}\) 的方案数
初始状态 f[0][inf][inf][inf] = 1,inf 为 \(>m\) 的数
复杂度 \(O(nm^4)\)
const int P = 998244353;
int n, m, f[1001][12][12][12];
void sol() {
cin >> n >> m;
f[0][m + 1][m + 1][m + 1] = 1;
for(int i = 1; i <= n; i++)
for(int a = 1; a <= m + 1; a++)
for(int b = 1; b <= m + 1; b++)
for(int c = 1; c <= m + 1; c++)
for(int x = 1; x <= m; x++)
if(x <= a) (f[i][x][b][c] += f[i-1][a][b][c]) %= P;
else if(x <= b) (f[i][a][x][c] += f[i-1][a][b][c]) %= P;
else if(x <= c) (f[i][a][b][x] += f[i-1][a][b][c]) %= P;
int ans = 0;
for(int a = 1; a <= m; a++)
for(int b = 1; b <= m; b++)
for(int c = 1; c <= m; c++)
(ans += f[n][a][b][c]) %= P;
cout << ans;
}

浙公网安备 33010602011771号