zoukankan      html  css  js  c++  java
  • 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
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Akka框架使用注意点
    log4j配置文件加载
    iptables常规使用
    linux ipv6临时地址
    组合数取模Lucas定理及快速幂取模
    Shell变量的定义与赋值操作注意事项
    虚拟机软件bochs编译使用问题
    实现一个简陋操作系统的相关笔记日志
    linux内核增加系统调用--Beginner's guide
    c语言几种异常
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/5523762.html
Copyright © 2011-2022 走看看