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

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

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

那么,对于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的复杂度。显然是不行的。但是j和k的范围是会被i约束的。于是我优化了j那一层,本地就能跑得很快了。设置了一个from和to表示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;
}

时间: 2024-10-11 09:46:58

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

51nod 1412 AVL树的种类(dp)

题目链接:51nod 1412 AVL树的种类 开始做的时候把深度开得过小了结果一直WA,是我天真了.. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 using namespace std; 6 typedef long long ll; 7 const int mod = 1e9+7; 8 const int N = 2001; 9 ll

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

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1412 题意: 思路: 经典dp!!!可惜我想不到!! $dp[i][k]$表示i个结点,最大深度为k的形态数. 它的转移方程就是: dp[i][k] += dp[i - 1 - j][k - 1] * dp[j][k - 1] dp[i][k] += 2 * dp[i - 1 - j][k - 2] * dp[j][k - 1] j是右子树结点个数,如果除去根结点,是不

ACM学习历程——HDU4814 Golden Radio Base(数学递推) (12年成都区域赛)

Description Golden ratio base (GRB) is a non-integer positional numeral system that uses the golden ratio (the irrational number (1+√5)/2 ≍ 1.61803399 symbolized by the Greek letter φ) as its base. It is sometimes referred to as base-φ, golden mean b

ACM学习历程—SNNUOJ 1110 A Simple Problem(递推 &amp;&amp; 逆元 &amp;&amp; 组合数学 &amp;&amp; 快速幂)(2015陕西省大学生程序设计竞赛K题)

Description Assuming a finite – radius “ball” which is on an N dimension is cut with a “knife” of N-1 dimension. How many pieces will the “ball” be cut into most?However, it’s impossible to understand the following statement without any explanation.L

51nod 1412 AVL数的种类(DP

题意给了n个节点的AVL数 问种类 树的深度不大 那么转移方程很明显了 dp[i][j]   代表的是节点为n深度为j的树的种类 k为左子树的节点个数 //dp[i][j+1] += dp[k][j]*dp[i-k-1][j];//dp[i][j+1] += 2*dp[k][j-1]*dp[i-k-1][j]; #include <stdio.h> #include <iostream> #include <algorithm> #include <string.

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

http://www.51nod.com/contest/problem.html#!problemId=1685 这是这次BSG白山极客挑战赛的E题. 这题可以二分答案t. 关键在于,对于一个t,如何判断它是否能成为第k大. 将序列中大于t的置为1,小于t的置为-1,等于t的置为0.那么区间中位数大于t的和就大于0,小于t的就小于0.于是就是判断区间和大于0的个数是否小于等于k. 维护前缀和sum(i),然后统计之前sum(j)小于sum(i)的有多少个,就是以i为右值的区间和大于0的个数.于

ACM学习历程—HDU4417 Super Mario(树状数组 &amp;&amp; 离线)

Problem Description Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble again and Mario needs to save his lover. We regard the road to the boss’s castle as a line (

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

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1770 这是这次BSG白山极客挑战赛的A题.由于数字全部相同,乘上b必然会有循环节,于是模拟乘法,记录数据,出现循环就退出即可. 代码: #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring>

ACM学习历程—HDU 5023 A Corrupt Mayor&#39;s Performance Art(广州赛区网赛)(线段树)

Problem Description Corrupt governors always find ways to get dirty money. Paint something, then sell the worthless painting at a high price to someone who wants to bribe him/her on an auction, this seemed a safe way for mayor X to make money. Becaus