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;
}
posted @ 2023-01-19 11:37  Bellala  阅读(34)  评论(0)    收藏  举报