acdream 1412 2-3 Trees

2-3 Trees

Time Limit: 12000/6000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)

Problem Description

      2-3 tree is an elegant data structure invented by John Hopcroft. It is designed to implement the same functionality as the binary search tree. 2-3 tree is an ordered rooted tree with the following properties:

  • the root and each internal vertex have either 2 or 3 children;
  • the distance from the root to any leaf of the tree is the same.

      The only exception is the tree that contains exactly one vertex — in this case the root of the tree is the only vertex, and it is simultaneously a leaf, i.e. has no children. The main idea of the described properties is that the tree with l leaves has the height O(log l).
      Given the number of leaves l there can be several valid 2-3 trees that have l leaves. For example, the picture below shows the two possible 2-3 trees with exactly 6 leaves.


      Given l find the number of different 2-3 trees that have l leaves. Since this number can be quite large, output it modulo r.

Input

      Input file contains two integer numbers: l and r (1 ≤ l ≤ 5 000, 1 ≤ r ≤ 109).

Output

      Output one number — the number of different 2-3 trees with exactly l leaves modulo r.

Sample Input

6 1000000000
7 1000000000

Sample Output

2
3

題解及代碼:

       這是一個DP題目,其實就是找到每一層上2*x+3*y=n的解的情況,然後由這一層推到上一層2*x‘+2*y’=x+y,依次類推,直到最高層。

注意:2 2 3  與2 3 2 是不同的情況,所以要用到組合數。我一開始直接開long long的數組,爆內存了,後來改寫成int ,然後數組開小爲原來的1/8,才過。

也看了一下別人的代碼,直接用的滾動數組,更省內存,而且速度也很快。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
typedef long long LL;
LL sum[5010];
int bt[2510][1300];
int N,R;
bool flag[5010];

struct node
{
    int x,y;
    node(int X,int Y)
    {
        x=X;y=Y;
    }
};

struct Root
{
    vector<node> nt;

}r[5010];


void get(int n)
{
    if(flag[n]) return;
    int j;
    for(int i=0;i*2<=n;i++)
    {
        j=n-i*2;
        if(j>=0&&j%3==0)
        r[n].nt.push_back(node(i,j/3));
    }
    flag[n]=true;
}

void init()
{
    memset(sum,-1,sizeof(sum));
    memset(flag,false,sizeof(flag));
    sum[1]=0;sum[2]=1;sum[3]=1;
    bt[1][0]=bt[1][1]=1;bt[1][2]=0;
    int bN=N/2+1;
    int bM=bN/2+1;
    get(N);

    for(int i=2;i<=bN;i++)
    {
        bt[i][0]=1;
        for(int j=1;j<=bM;j++)
        {
            bt[i][j]=(bt[i-1][j-1]+bt[i-1][j])%R;
        }
    }
}

LL dfs(int n)
{
    if(sum[n]>=0) return sum[n];
    int len=r[n].nt.size();
    LL ans=0;int k;
    for(int i=0;i<len;i++)
    {
        k=r[n].nt[i].x+r[n].nt[i].y;
        get(k);
        ans=(ans+bt[k][min(r[n].nt[i].x,r[n].nt[i].y)]*dfs(k))%R;
    }
    //printf("%d  %d\n",n,ans);
    sum[n]=ans;
    return ans;
}

int main()
{
    while(scanf("%d%d",&N,&R)!=EOF)
    {
        if(N==1)
        {
            printf("%d\n",N%R);
            continue;
        }
        init();
        LL an=dfs(N);
        printf("%lld\n",an);
    }
    return 0;
}








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章