HDU 4359 and
Codeforces 9d is similar,
The competition failed to recall how it was previously done.
Codeforces 9D. All vertices in the left subtree of the current vertex must be less than the vertices of the current vertex. the vertices of the current vertex must be less than all vertices of the right subtree, how many different shapes are there in the tree with n vertices depth> = H?
Example
The depth of the three points is greater than or equal to 2.
For example
Apply the question of codeforces
DenoteTNHThe
Number of Binary Search Trees on N nodes with height equal to H. We will derive a recurrent formulaTNH.
For the base case note thatT00 bytes = 1_1 (empty
Tree), andTI0 bytes = averageT0IElse = else 0 if
I> 0.
Now take any binary search tree on N nodes with height equal to H. Let M be the number written at its root, 1 limit ≤ limitMLimit ≤ limitN.
The left subtree is a binary search tree M-1 nodes, and the right subtree is a binary search tree on n-M nodes. the maximal of their heights must be equal to h-1. consider 2 subcases:
1. The height of the Left subtree is equal to h-1. There areTMAccept-limit 1, limit,HExample-Example 1 such
Trees. The right subtree can have any height from 0 to h-1, so there are such
Trees. Since we can choose left and right Subtrees independently, We have variants
In this case.
2. The height of the Left subtree is less than h-1. There are such
Trees, And the right subtree must have height exactly h-1, which gives us totally variants.
So the recurrent formula is the following :.
All the valuesTNHCan
Be calculated by dynamic programming. The answer, then, is.
Well understood, but there is another method
DP [I] [J] indicates the total number of trees whose I points constitute a height less than or equal to J. The writing method is naturally a little simple.
My code
#include<cstdio>#include<cstring>typedef __int64 lld;lld dp[36][36];int main(){for(int i=0;i<=35;i++) dp[0][i]=1;for(int i=1;i<=35;i++){for(int j=1;j<=35;j++){for(int k=0;k<i;k++){dp[i][j]+=dp[k][j-1]*dp[i-k-1][j-1];//printf("i=%d j=%d %I64d\n",i,j,dp[j][j]);}}}int n,h;scanf("%d%d",&n,&h);printf("%I64d\n",dp[n][35]-dp[n][h-1]);return 0;}
HDU 4359
Note that the current root node can be retrieved at will, because the question only requires the sum of the Left subtree to be smaller than the right subtree, as long as the maximum value of the Left subtree is smaller than the maximum value of the right subtree, because 2 ^ 0 + 2 ^ 1 + 2 ^ p-1 <2 ^ p.
Therefore, when obtaining DP [I] [J,
1: n-1-1 vertices in the subtree are in the left subtree or all in the right subtree, because in this case, no restrictions are imposed.
Now
2: if there are left and right subtree, then the biggest must be placed on the right subtree, So in addition to the current root and the largest point, other points (total I-2) random take, enumerate the number of left subtree values, and the number of right subtree values at most.
Transfer:
dp[i][j]+=C[i-2][k]*dp[k][j-1]*dp[i-1-k][j-1];
This is much simpler than the nominal one (the Code HDU is currently the shortest), but pay special attention to the initialization details.
DP [I] [J]: Total number of trees when I point depth is less than or equal to J
#include<cstdio>#include<cstring>const int mod = 1000000007;typedef __int64 lld;const int N = 360;lld dp[361][361];lld C[361][361];int main(){ C[0][0]=1; for(int i=1;i<=N;i++){ C[i][0]=C[i][i]=1; for(int j=1;j<i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; } memset(dp,0,sizeof(dp)); for(int i=0;i<=N;i++) dp[0][i]=1; for(int i=1;i<=N;i++) dp[1][i]=1; for(int i=2;i<=N;i++){ for(int j=1;j<=N;j++){ dp[i][j]+=dp[i-1][j-1]*2%mod; dp[i][j]%=mod; for(int k=1;k<=i-2;k++){ dp[i][j]+=(C[i-2][k]*dp[k][j-1])%mod*dp[i-1-k][j-1]%mod; dp[i][j]%=mod; } dp[i][j]*=i; dp[i][j]%=mod; } } int n,h,t,ca=1; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&h); printf("Case #%d: %I64d\n",ca++,((dp[n][h]-dp[n][h-1])%mod+mod)%mod); } return 0;}