题意:
给定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; }