HDU 4359 Easy Tree DP? 띠권 두 갈래 나무의 구조 방법 dp

2665 단어
제목:
ndeep 지정
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; }

좋은 웹페이지 즐겨찾기