Acdream 1412 2-3 Trees, acdream1412
2-3 Trees
Time Limit:12000/6000 MS (Java/Others)
Memory Limit:128000/64000 KB (Java/Others) SubmitStatusProblem Description
2-3 tree is an elegant data structure partitioned ted 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 file contains two integer numbers: l and r (1 ≤ l ≤ 5 000, 1 ≤ r ≤109 ). output one number-the number of different 2-3 trees with exactly l leaves modulo r. sample Input
6 10000000007 1000000000
Sample Output
23
Question and code:
This is a DP question. In fact, it is to find the solution of 2 x + 3 * y = n on each layer, then, push the layer to the top layer 2 * x' + 2 * y' = x + y, and so on until the top layer.
Note: The numbers 2 2 3 and 2 3 2 are different, so the number of combinations is used. I started to open the long array directly, burst the memory, and then changed it to int, and then the array was opened as small as 1/8.
I also looked at other people's code and used the scrolling array directly to save more memory and speed.
#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;}