ACM学习历程—51NOD 1412 AVL树的种类(递推)

Posted AndyQsmart

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM学习历程—51NOD 1412 AVL树的种类(递推)相关的知识,希望对你有一定的参考价值。

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1770

这是这次BSG白山极客挑战赛B题。设p(i, j)表示节点个数为i,高度为jAVL树的个数。

那么,对于1 <= k <= i-1

p[i][j] += p[k][j-1]*p[i-1-k][j-1]%MOD;

p[i][j] += p[k][j-2]*p[i-1-k][j-1]%MOD;

p[i][j] += p[k][j-1]*p[i-1-k][j-2]%MOD;

但是这样模拟是n^3的复杂度。显然是不行的。但是jk的范围是会被i约束的。于是我优化了j那一层,本地就能跑得很快了。设置了一个fromto表示j这一维跑的范围,那么每次这一次j的最小值就是下一次from,这一次j的最大值就是下一次的to。如此即可。

 

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
#define LL long long
#define MOD 1000000007

using namespace std;

const int maxN = 2002;
LL p[maxN][maxN];

void init()
{
    int from, to, tfrom, tto;
    memset(p, 0, sizeof(p));
    p[0][0] = 1;
    p[1][1] = 1;
    from = 0; to = 1;
    for (int i = 2; i < maxN; ++i)
    {
        tfrom = to;
        tto = from;
        to++;
        for (int j = from; j <= to; ++j)
        {
            for (int k = 0; k < i; ++k)
            {
                p[i][j] += p[k][j-1]*p[i-1-k][j-1]%MOD;
                if (j > 1)
                {
                    p[i][j] += p[k][j-2]*p[i-1-k][j-1]%MOD;
                    p[i][j] += p[k][j-1]*p[i-1-k][j-2]%MOD;
                }
                p[i][j] %= MOD;
                if (p[i][j])
                {
                    tfrom = min(tfrom, j);
                    tto = max(tto, j);
                }
            }
        }
        from = tfrom;
        to = tto;
    }
    //cout << "OK"<<endl;
}

int main()
{
    //freopen("test.in", "r", stdin);
    init();
    int n;
    while (scanf("%d", &n) != EOF)
    {
        int ans;
        LL t = 0;
        for (int i = 1; i <= n; ++i) t = (t+p[n][i])%MOD;
        ans = t;
        printf("%d\\n", ans);
    }
    return 0;
}
View Code

 

以上是关于ACM学习历程—51NOD 1412 AVL树的种类(递推)的主要内容,如果未能解决你的问题,请参考以下文章

51nod 1412 AVL树的种类(dp)

51nod 1412 AVL树的种类(经典dp)

51nod 1412 AVL数的种类(DP

ACM学习历程—51NOD 1770数数字(循环节)

ACM学习历程—51NOD 1685 第K大区间2(二分 && 树状数组 && 中位数)

ACM/ICPC 之 DP进阶(51Nod-1371(填数字))