[CF9D]How Many Trees?_动态规划_树形dp_ntt

How many trees?

题目链接https://www.codeforces.com/contest/9/problem/D

数据范围:略。


题解

水题。

$f_{i,j}$表示$i$个节点,最大深度为$j$的方案,$g_{i,j}=\sum\limits_{k = 1}^{j - 1} f_{i, k}$。

显然,如果我们枚举深度的话,可以用$ntt$优化卷积。

这里写的$O(n^3)$。

代码

#include <bits/stdc++.h>

#define setIO(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout) 

#define N 2010 

using namespace std;

typedef long long ll;

const int mod = 998244353 ;

int qpow(int x, int y) {
    int ans = 1;
    while (y) {
        if (y & 1) {
            ans = (ll)ans * x % mod;
        }
        y >>= 1;
        x = (ll)x * x % mod;
    }
    return ans;
}

int f[N][N], g[N][N], a[N], b[N];

int main() {
    // setIO("count");
    int n, h;
    cin >> n >> h ;
    f[1][1] = 1;
    g[0][0] = 1;
    for (int dep = 1; dep <= n; dep ++ ) {
        g[dep][0] = 1;
    }
    for (int dep = 2; dep <= n; dep ++ ) {
        g[dep][1] = 1;
    }
    for (int dep = 2; dep <= n; dep ++ ) {
        // for (int i = 1; i <= n; i ++ ) {
        //     a[i] = f[dep - 1][i], b[i] = g[dep - 1][i];
        // }
        // a * a + 2 * a * b
        for (int l = 0; l <= n; l ++ ) {
            for (int r = 0; r <= n; r ++ ) {
                if (l + r + 1 <= n) {
                    (f[dep][l + r + 1] += (ll)f[dep - 1][l] * f[dep - 1][r] % mod) %= mod;
                    (f[dep][l + r + 1] += (ll)f[dep - 1][l] * g[dep - 1][r] % mod * 2 % mod) %= mod;
                }
            }
        }
        for (int i = 1; i <= n; i ++ ) {
            g[dep][i] = (g[dep - 1][i] + f[dep - 1][i]) % mod;
        }
        // printf("Dep : %d\n", dep);
        // for (int j = 1; j <= n; j ++ ) {
        //     printf("%d ", f[dep][j]);
        // }
        // puts("");
    }
    int ans = 0;
    for (int i = h; i <= n; i ++ ) {
        (ans += 
        f[i][n]) %= mod;
    }
    cout << ans << endl ;
    return 0;
}
posted @ 2019-10-31 18:22  JZYshuraK_彧  阅读(...)  评论(...编辑  收藏