2-3 Trees
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
Output
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;
}