hdu 5370 Tree Maker(catalan+dp)

来源:互联网 发布:android http网络协议 编辑:程序博客网 时间:2024/06/09 23:55

题目链接:hdu 5370 Tree Maker


n个节点的二叉树种类为Catalan数的第n项

对于一棵子树而言,被移动过的节点就是确定的位置,所以只要知道已经确定位置的K个节点有多少个空孩子指针M,和就该子树下的N个未确定位置的节点,等于是说用N个节点构造M个可为空的子树的种类数。对于整个树的形态数即为若干棵独立的子树形态数的乘积。

定义dp[i][j]为用i个节点构造j棵树的形态数,dp[i][j] = sum{ dp[i-1][j-k] * catalan[k] | 0 ≤ k ≤j }, 用o(n^3)的复杂度预处理出dp数组。然后模拟操作后计算出每个子树的M和N。


#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long ll;const int maxn = 505;const int mod = 1e9 + 7;int dp[maxn][maxn], catalan[maxn];void preserve () {catalan[0] = catalan[1] = 1;for (int i = 2; i <= 500; i++) {for (int j = 0; j < i; j++)catalan[i] = (catalan[i] + (ll) catalan[j] * catalan[i-j-1]) % mod;}dp[0][0] = 1;for (int i = 1; i <= 500; i++) {for (int j = 0; j <= 500; j++) {for (int k = 0; k <= j; k++)dp[i][j] = (dp[i][j] + (ll) dp[i-1][j-k] * catalan[k]) % mod;}}}int N, M, far[maxn], son[maxn][2], idx[maxn], cnt[maxn], sum[maxn];inline int newNode (int f) {M++;cnt[M] = son[M][0] = son[M][1] = 0;far[M] = f;return M;}void init () {M = 0;int u = newNode(1), t, k;idx[u] = M;for (int i = 1; i <= N; i++) {scanf("%d", &t);if (t == 0)u = far[u];else if (t <= 2) {if (son[u][t-1] == 0) {son[u][t-1] = newNode(u);idx[son[u][t-1]] = idx[u];cnt[idx[u]]--;}u = son[u][t-1];} else {scanf("%d", &k);son[u][t-3] = newNode(u);cnt[son[u][t-3]] = k - 1;idx[son[u][t-3]] = son[u][t-3];}}memset(sum, 0, sizeof(sum));for (int i = 1; i <= M; i++) {if (son[i][0] == 0)sum[idx[i]]++;if (son[i][1] == 0)sum[idx[i]]++;}}int solve () {int ret = 1;for (int i = 1; i <= M; i++) {if (idx[i] != i)continue;ret = (ll) ret * dp[sum[i]][cnt[i]] % mod;}return ret;}int main () {preserve();int cas = 1;while (scanf("%d", &N) == 1) {init ();printf("Case #%d: %d\n", cas++, solve ());}return 0;}


0 0
原创粉丝点击