51Nod-1412-AVL树的种类

来源:互联网 发布:中级经济师题库软件 编辑:程序博客网 时间:2024/05/19 03:46

ACM模版

描述

描述

题解

经典的dp,而我却没有想到……树的深度不大,可以实现暴力枚举深度。
设dp[i][k]表示结点个数为i,深度为k的AVL个数。

那么,状态转移方程为(j表示右子树的结点数目):

1、dp[i][k] += dp[i - 1 - j][k - 1] * dp[j][k - 1]
2、dp[i][k] += 2 * dp[i - 1 - j][k - 2] * dp[j][k - 1]

可以使用FFT优化一下!!!

代码

One:

#include <iostream>#include <cstdio>#define MOD 1000000007using namespace std;const int MAXN = 2001;const int tier = 11;typedef long long ll;ll dp[MAXN][tier];void init(){    dp[0][0] = 1;    dp[1][1] = 1;    for (int i = 2; i < MAXN; i++)    {        for (int k = 2; k < tier; k++)        {            for (int j = 0; j < i; j++)            {                dp[i][k] += dp[i - j - 1][k - 1] * dp[j][k - 1];                dp[i][k] %= MOD;                dp[i][k] += 2 * dp[i - j - 1][k - 2] * dp[j][k - 1];                dp[i][k] %= MOD;            }        }    }    return ;}int main(){    int n;    init();    while (scanf("%d", &n) == 1)    {        ll ans = 0;        for (int i = 1; i < tier; i++)        {            ans += dp[n][i];            ans %= MOD;        }        printf("%lld\n", ans);    }    return 0;}

Two:

#include <stdio.h>#define LL long long#define P 1000000007#define MAXN 2000#define MAXL 15int min[MAXL + 1];int max[MAXL + 1];int dp[MAXN + 1][MAXL + 1];int solve(int n){    min[0] = max[0] = 0;    //    min[1] = max[1] = 1;    //  第i层的最右端结点序号    for (int i = 2; i <= MAXL; ++i)    {        min[i] = min[i - 1] + min[i - 2] + 1;        max[i] = (1 << i) - 1;    }    dp[0][0] = dp[1][1] = 1;    for (int i = 2; i <= n; ++i)    {        for (int lv = 2; lv <= MAXL && i >= min[lv]; ++lv)        {            if (i > max[lv])            {                continue;            }            for (int x = 0, y = i - 1; y >= 0; ++x, --y)            {                dp[i][lv] = (dp[i][lv] + (LL)dp[x][lv - 1] * dp[y][lv - 1]                          + (LL)dp[x][lv - 1] * dp[y][lv - 2]                          + (LL)dp[x][lv - 2] * dp[y][lv - 1]) % P;            }        }    }    int ans = 0;    for (int lv = 0; lv <= MAXL; ++lv)    {        ans = (ans + dp[n][lv]) % P;    }    return ans;}int main(){    int n;    scanf("%d", &n);    printf("%d\n", solve(n));    return 0;}
0 0