acdream 1412 2-3Trees (组合+DP)

题意:2-3树的每个结点(除了叶子外)有2或3个孩子(分支),假设是一个满2-3树,那么给出叶子的数量,求这样的树有多少棵。(注:有2个孩子的结点视为相同,有3个孩子的结点视为相同,比如倒数第2层有4个结点,且叶子有4+6=10个,即2个有2孩的结点在前面,2个有3孩的结点在后面,那么头两个结点的孩子互换是视为相同的,如下图)

只要结点1234各自的孩子数不变,则视为同棵树。若具有2孩的结点跟具有3孩的结点换位置,则为不同树,比如1和3换个位置。)

思路:

(1)考虑DP,依靠叶子数量小的,推出叶子数量大的。dp[k]表示叶子数为k的树有多少棵。那么只有一个结点的情况dp[1]=1我们是知道的。

(2)如何dp?

  dp[k]可以更新后面的点有dp[2k~3k],将k看成倒数第2层,那么其每个结点可以决定最底层的叶子个数。比如第1个结点生2孩,其他结点生3孩,可以更新dp[1*2+(k-1)*3]。

  这一步只需要枚举2的个数即可,2的个数可以从0→k。设k=a+b,a个生2孩,b个生3孩,那么q=a*2+b*3为我们可以更新的点,则dp[q]+=dp[k]*c[k][a],这里c[k][a]的意思是组合数学中Ck取a的组合数。任何一个dp[x]都可能被多个不同的2-3树发展多一层而变来的,例如dp[3]可以更新dp[9],dp[4]当3个结点生2孩,1个结点生3孩也可以更新到dp[9],。

(3)需要预先求得c[x][y]的所有可能,因为后面可能多次引用,逐个计算复杂度会过高。

 1 #include <bits/stdc++.h>
 2 #define LL long long
 3 using namespace std;
 4 const int N=5005;
 5 LL dp[N*3];
 6 LL c[N/2][N/2];
 7
 8 unsigned int n,r;
 9 void pre()   //组合数,类似于一个黑色的袋子中摸出黑球和白球,黑白球代表2或3孩子,组成有序序列
10 {
11     memset(c,0,sizeof(c));
12     c[0][0]=1;
13     c[1][0]=c[1][1]=1;
14     for(int i=2;i<=n/2;i++)
15     {
16         c[i][0]=1;
17         for(int j=1;j<i;j++)
18             c[i][j]=(c[i-1][j-1]%r+c[i-1][j]%r)%r;
19
20         c[i][i]=1;
21     }
22 }
23 void init()
24 {
25     memset(dp,0,sizeof(dp));
26     dp[1]=1;
27     for(int i=1; i<n/2+1; i++)   //从前面开始更新到后面,2500还能更新5000的,所以要循环到n/2
28     {
29         for(int j=0; j<=i; j++) //有j个2,  i-j个3
30         {
31             int q=j*2+(i-j)*3; //要更新的点
32             dp[q]=(dp[q]+(dp[i]*c[i][j]))%r;
33         }
34     }
35 }
36
37 int main()
38 {
39     //freopen("e://input.txt", "r", stdin);
40     while(~scanf("%d%d",&n,&r))
41     {
42         pre();
43         init();
44         printf("%lld\n",dp[n]);
45     }
46     return 0;
47 }

AC代码

时间: 2024-10-09 12:18:38

acdream 1412 2-3Trees (组合+DP)的相关文章

HDU 4832 Chess 排列组合 DP

Chess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 351    Accepted Submission(s): 124 Problem Description 小度和小良最近又迷上了下棋.棋盘一共有N行M列,我们可以把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,"王"在棋盘 上的走法遵循十字

Acdream 1076 XXX的机器人(dp + 线段树)

题目链接:http://acdream.info/problem?pid=1076 这题DP的状态很好设计,dp[i][j]表示指令i的时候,全排列状态是j,全排列一共就120个,预处理出来就可以了 那么问题就在于对于一个指令怎么快速获得这个整个区间的置换乘积,这步其实利用一个线段树维护就可以了,但是要注意置换是不满足交换律的,所以正序逆序都要保存一遍 代码: #include <cstdio> #include <cstring> #include <algorithm&g

acdream 1429 Rectangular Polygon【dp】

题目:acdream 1429 Rectangular Polygon 题意:给出n个数,是边长,然后问你能不能组成多边形,其边必须是平行于x轴或者平行于y轴的.如果可以的话输出任意一种方案. 分析:分析发现,就是给你一堆数,然后让你尽可能挑出多的数,分成两部分的和相等,我们可以用dp来解决这个问题. 定义dp[i][j] 前 i 个数中挑出一些书其两部分的差值是 j 的最大个数. 转移方程: dp[i][j] = max(dp[i][j],dp[i-1][j]); //不放 dp[i][j-a

acdream 1409 Musical 状压DP

链接:http://acdream.info/problem?pid=1409 题意:整个国家有n座城市,每座城市有三种粉丝. 第一种一周看一场音乐剧,挑选的音乐剧是已经在周围城市播放上演过的次数最多的音乐剧中的随机一个. 第二种每天看一场音乐剧,挑选的是在本城市上映的音乐剧中的随机一个. 第三种每天看一场音乐剧,挑选的是在本城市以及周围城市中上映的音乐剧中的随机一个. 周围的城市是指这座城市与当前城市之间存在路径. 我现在要带着一部音乐剧环游全国(可以坐飞机,不用走路径),每座城市呆一周,并且

ACdream 1113 The Arrow (概率dp求期望)

E - The Arrow Time Limit:1000MS     Memory Limit:64000KB     64bit IO Format:%lld & %llu Submit Status Description The history shows that We need heroes in every dynasty. For example, Liangshan Heroes. People hope that these heroes can punish the bad

acdream 1412 2-3 Trees

2-3 Trees Time Limit: 12000/6000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatus Problem Description 2-3 tree is an elegant data structure invented by John Hopcroft. It is designed to implement the same functionality as the bi

Acdream 1113 The Arrow(概率dp)

题目链接:传送门 题意: 初始状态在0,每次丢骰子[1,6],如果现在在x,丢的骰子数为y,如果x+y>n那么就还停留在x. 求从0到n所丢骰子次数的期望. 分析: 这题和之前的就更改了一点就是如果现在在x,丢的骰子数为y,如果x+y>n那么就还停留在x. 那么我们设dp[i]表示从i到n要丢的骰子次数的期望 那么 我们设每次有x次的可能留在原地 dp[i] =dp[i]*y/6+dp[i+1]/6+dp[i+2]/6..+1; 然后化简一下得到dp[i]的公式. 代码如下: #include

nyoj1076-方案数量 【排列组合 dp】

http://acm.nyist.net/JudgeOnline/problem.php?pid=1076 方案数量 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 给出一个N*M的棋盘,左下角坐标是(0,0),右上角坐标是(N,M),规定每次只能向上或者向右走,问从左下角走到右上角,一共有多少种方案.上图是一个4*3的棋盘. 输入 多组测试数据.每组输入两个整数N,M(0≤N,M≤30).输入0,0时表示结束,不做任何处理. 输出 对于每组测试数据,输出对应的方案

Acdream 1132 Chess(状压dp)

Chess Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statistic Next Problem Problem Description Xiang-qi is a kind of traditional Chinese chess. There is a special role in the game called "Jiang" (or call