1 /* 2 題目大意:給n個節點的二叉樹第i個節點的權值爲2^(i-1), 3 求全部含左右子樹的節點都符合左子樹的權和小於右子樹權和的種數。 4 */ 5 #include <iostream> 6 #include <cstdio> 7 #include <cstring> 8 using namespace std; 9 10 typedef __int64 LL; 11 const int maxn=365; 12 const int mod=1e9+7; 13 LL c[maxn][maxn]; 14 LL dp[maxn][maxn];//i個節點,深度不超過j的子數個數 15 16 void getcombinations() 17 { 18 memset(c,0,sizeof(c));c[0][0]=1; 19 for(int i=1;i<maxn;i++) 20 { 21 c[i][0]=1; 22 for(int j=1;j<=i;j++) 23 c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod; 24 } 25 } 26 27 void init() 28 { 29 getcombinations(); 30 int i,j,k; 31 for(i=1;i<maxn;i++) dp[1][i]=1; 32 for(i=2;i<maxn;i++) 33 { 34 for(j=1;j<maxn;j++) 35 { 36 dp[i][j]=i*dp[i-1][j-1]*2%mod;//i個點選一個出來作根,只有一顆子樹,能夠放左也能夠右 37 for(k=1;k<=i-2;k++) 38 /* 39 根據等比數列求和公式2^0+2^1+......+2^(n-1)=2^n-1 < 2^n 40 i個節點有兩個子樹,選1個出來作根有i種,把剩餘節點中權最大的給右子樹 41 ,那麼就是i-2個點選k個點作左子樹,剩下的都作右子樹。 42 (c(i,1)*c(1,1)*c(i-2,k)*c(i-2-k,i-2-k)*dp(k,j-1)*dp(i-1-k,j-1)) 43 */ 44 dp[i][j]=(dp[i][j]+i*c[i-2][k]%mod*dp[k][j-1]%mod*dp[i-1-k][j-1]%mod)%mod; 45 } 46 } 47 } 48 int main() 49 { 50 init(); 51 int t,icase=0,n,d; 52 scanf("%d",&t); 53 while(t--) 54 { 55 scanf("%d %d",&n,&d); 56 printf("Case #%d: %I64d\n",++icase,(mod+dp[n][d]-dp[n][d-1])%mod); 57 } 58 return 0; 59 }