zoukankan      html  css  js  c++  java
  • HDU 4359 Easy Tree DP? 带权二叉树的构造方法 dp

    题意:

    给定n deep

    1、构造一个n个节点的带权树,且最大深度为deep,每一个节点最多仅仅能有2个儿子

    2、每一个节点的值为2^0, 2^1 ··· 2^(n-1)  随意两个节点值不能同样

    3、对于一个节点,若他有左右儿子,则左子树的和 < 右子树的和

    问:

    有多少种构造方法。

    思路:

    dp


    #include <stdio.h>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    template <class T>
    inline bool rd(T &ret) {
        char c; int sgn;
        if(c=getchar(),c==EOF) return 0;
        while(c!='-'&&(c<'0'||c>'9')) c=getchar();
        sgn=(c=='-')?-1:1;
        ret=(c=='-')?0:(c-'0');
        while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
        ret*=sgn;
        return 1;
    }
    template <class T>
    inline void pt(T x) {
        if (x <0) {
            putchar('-');
            x = -x;
        }
        if(x>9) pt(x/10);
        putchar(x%10+'0');
    }
    ///////////////////////////////////
    typedef long long ll;
    const int N = 362;
    const ll mod = 1000000000 + 7;
    
    int d[N][N], p[N][N], c[N][N];
    int main() {
    	memset(d, 0, sizeof d);
    	memset(p, 0, sizeof p);
    	memset(c, 0, sizeof c);
    	for (int i = 0; i < N; ++i) {
    		c[i][0] = c[i][i] = 1;
    		for (int j = 1; j < i; ++j)
    			c[i][j] = (c[i - 1][j] + c[i-1][j-1]) % mod;
    	}
    	for (int i = 0; i < N; ++i)
    		p[0][i] = 1;
    	for (int i = 1; i < N; ++i)
    		p[1][i] = 1;
    	for (int i = 2; i < N; ++i)
    		for (int j = 1; j < N; ++j) {
    			p[i][j] += (ll)p[i-1][j-1] * 2 % mod;
    			p[i][j] %= mod;
    			if (i - 1 >= 2) {
    				for (int k = 1; k <= i - 2; ++k) {
    					p[i][j] += ((ll)c[i-2][k] * p[k][j-1] % mod) * p[i-1-k][j-1] % mod;
    					p[i][j] %= mod;
    				}
    			}
    			p[i][j] = (ll)p[i][j] * i % mod;
    		}
    	//int x, y; while (~scanf("%d%d", &x, &y)) printf("%d
    ", p[x][y]);
    	d[1][1] = 1; d[0][0] = 1;
    	for (int i = 2; i < N; ++i)
    		for (int j = i; j < N; ++j) {
    			d[i][j] += (ll)2 * d[i-1][j-1] % mod;
    			d[i][j] %= mod;
    			if (j - 1 >= 2) {
    				for (int k = 1; k <= j - 2; ++k) {
    					d[i][j] += ((ll)c[j-2][k] * p[k][i-2] % mod) * d[i-1][j-1-k] % mod;
    					d[i][j] %= mod;
    					d[i][j] += ((ll)c[j-2][k] * d[i-1][k] % mod) * p[j-1-k][i-2] % mod;
    					d[i][j] %= mod;
    					d[i][j] += ((ll)c[j-2][k] * d[i-1][k] % mod) * d[i-1][j-1-k] % mod;
    					d[i][j] %= mod;
    				}
    			}
    			d[i][j] = (ll)d[i][j] * j % mod;
    		}
    	int T = 0, cas, u, v;
    	scanf("%d", &cas);
    	while (cas -- > 0) {
    		rd(u); rd(v);
    		printf("Case #");
    		pt(++T);
    		putchar(':');
    		putchar(' ');
    		pt(d[v][u]);
    		putchar('
    ');
    	}
    	return 0;
    }


  • 相关阅读:
    SQL关闭连接,及分离数据库
    C# 用户选择单个压缩-系统自带压缩
    设计模式7大原则--01
    httpclient
    Mac idea 常用命令
    集合整理
    几种简单的排序算法
    基础数据结构简介
    git 常用命令3
    git 常用命令2
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4028412.html
Copyright © 2011-2022 走看看