线性dp——求01串最大连续个数不超过k的方案数,cf1027E 好题!

只写了和dp有关的。。博客 https://www.cnblogs.com/huyufeifei/p/10351068.html

关于状态的继承和转移

这题的状态转移要分开两步来做:

  1.继承之前状态的合法构造数量

  2.构造出该状态下特有的新构造数量

这类dp尽量由已知状态推出未知态(加法转移)来做。。。自己用减法转移都不知道边界怎么写。。

#include <cstdio>
#include <algorithm>

const int N = 510, MO = 998244353;

int f[N][N][2], sum[N];

inline void add(int &a, const int &b) {
    a = (a + b) % MO;
    return;
}

int main() {
    int n, k;
    scanf("%d%d", &n, &k);
    for(int j = 1; j <= n; j++) {
        f[0][j][0] = 1;
    }
    for(int i = 0; i <= n; i++) {
        for(int j = 1; j <= n; j++) {
            // f[i][j][0/1]继承前状态
            for(int k = 1; k < j && i + k <= n; k++) {
                add(f[i + k][j][0], f[i][j][0]);
                add(f[i + k][j][1], f[i][j][1]);
            }
            if(i + j <= n) {//构造出新的方案
                add(f[i + j][j][1], f[i][j][0]);
                add(f[i + j][j][1], f[i][j][1]);
            }
        }
    }
    
    for(int i = 1; i <= n; i++)printf("%d ", f[n][i][1]);
    long long ans = 0LL;
    for(int i = 1; i <= n; i++)
        for(int j = 1; (long long)j * i < k && j <= n; j++)
            ans = (ans + f[n][i][1] * f[n][j][1] % MO) % MO;
    ans = ans * 2 % MO;
    printf("%lld\n", ans);
}

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/10813789.html