hdu 4359 dp

 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 }
时间: 2024-08-10 09:18:59

hdu 4359 dp的相关文章

HDU 4359 Easy Tree DP?(是dp但并不是tree dp + 组合计数)

HDU 4359 题意:定义Bear Tree为一颗二叉树,这种二叉树每个结点有一个权值,范围在2^0~2^n-1,并且每个值只用一次,对于每个结点,如果同时存在左右子树,那么左子树的权值和要小于右子树的权值和.求点数为N,层次为D的Bear Tree的数量. 思路: 2^0 + 2^1 + ... + 2^n < 2^(n+1) 根据这个性质,我们可以得出权值最大节点必须在右子树上,并且只要同时存在左右子树,则将权值最大节点放在右子树上就一定符合条件. 所以我们用dp[i][j]表示点数为i且

HDU 4832(DP+计数问题)

HDU 4832 Chess 思路:把行列的情况分别dp求出来,然后枚举行用几行,竖用几行,然后相乘累加起来就是答案 代码: #include <stdio.h> #include <string.h> #include <iostream> using namespace std; typedef long long ll; const ll MOD = 9999991; const int N = 1005; int t, n, m, k, x, y; ll dp1

hdu 3944 dp?

DP? Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 128000/128000 K (Java/Others)Total Submission(s): 1804    Accepted Submission(s): 595 Problem Description Figure 1 shows the Yang Hui Triangle. We number the row from top to bottom 0,1,2,-a

hdu 5389 dp类似背包

http://acm.hdu.edu.cn/showproblem.php?pid=5389 Problem Description Zero Escape, is a visual novel adventure video game directed by Kotaro Uchikoshi (you may hear about ever17?) and developed by Chunsoft. Stilwell is enjoying the first chapter of this

hdu 1025 dp 最长上升子序列

1 //Accepted 4372 KB 140 ms 2 //dp 最长上升子序列 nlogn 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 using namespace std; 7 const int imax_n = 500005; 8 int dp[imax_n]; 9 int d[imax_n]; 10 int a[imax_n]; 11 int n; 12 int len

HDU 5928 DP 凸包graham

给出点集,和不大于L长的绳子,问能包裹住的最多点数. 考虑每个点都作为左下角的起点跑一遍极角序求凸包,求的过程中用DP记录当前以j为当前末端为结束的的最小长度,其中一维作为背包的是凸包内侧点的数量.也就是 dp[j][k]代表当前链末端为j,其内部点包括边界数量为k的最小长度.这样最后得到的一定是最优的凸包. 然后就是要注意要dp[j][k]的值不能超过L,每跑一次凸包,求个最大的点数量就好了. 和DP结合的计算几何题,主要考虑DP怎么搞 /** @Date : 2017-09-27 17:27

HDU 4901 DP背包

给你n个数,问你将数分成两个数组,S,T ,T 中所有元素的需要都比S任意一个大,问你S中所有元素进行 XOR 操作和 T 中所有元素进行 &操作值相等的情况有多少种. DP背包思路 dpa[i][j][0]  表示从左开始到i,不取i,状态为j的方案数 dpa[i][j][1]  表示从作开始到i,取i,状态为j的方案数 dpb[i][j]      表示从右开始到i,状态为j的方案数 因为S集合一定在T集合的左边,那么可以枚举集合的分割线,并且枚举出的方案要保证没有重复,如果要保证不重复,只

HDU 4359 Easy Tree DP?

Easy Tree DP? Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1487    Accepted Submission(s): 567 Problem Description A Bear tree is a binary tree with such properties : each node has a value o

!HDU 4359 左子树节点和小于右子树的树有多少种-dp

题意:n个节点,每个节点的权值为2^0,2^1....2^(n-1),求满足任何节点的左子树的节点和小于右子树的节点和的分配方案有多少种 分析: 由于等比数列的性质:1+2+....2^(k-1)<2^k,所以除了根节点的权值以外的,最大值必须在右子树,其余节点随意. 情况有:1.只有左子树,2.只有右子树,3.都有 dp[i][j]:表示选i个节点深度<=j的树的分配方案 转移:dp[i][j]+=C(i-2,k)*dp[k][j-1]*dp[i-1-k][j-1],这里用到了组合数性质,或