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; }