Solution
考虑这样DP:
dpi,j
表示
i−house
中有
j
条路径的方案数。
答案就是
考虑从
dpi−1,j
和
dpi−1,k
转移到的状态。
- 若不选取根, dpi,j+k+=dpi−1,jdpi−1,k 。
- 若选取根,根自成一条路径, dpi,j+k+1+=dpi−1,jdpi−1,k
- 若选取根,与其中一个子树中的点连成路径, dpi,j+k+=2dpi−1,jdpi−1,k∗(j+k)
- 若选取根,与两个子树中的点连成路径, dpi,j+k−1+=2(j+k2)dpi−1,j∗dpi−1,k
写完转移会发现每次
j
与
所以总复杂度是
O(n3)
的。
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 810;
const int MOD = 1000000007;
typedef long long ll;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
inline void read(int &x) {
static char c; x = 0;
for (c = get(); c < '0' || c > '9'; c = get());
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
}
int n;
ll res;
ll dp[N][N];
int main(void) {
read(n);
dp[1][1] = dp[1][0] = 1;
for (int i = 2; i <= n; i++)
for (int j = 0; j <= n; j++)
for (int k = 0; k + j <= n; k++) {
res = dp[i - 1][j] * dp[i - 1][k] % MOD;
dp[i][j + k] += 2 * res * (j + k) + res;
dp[i][j + k + 1] += res;
dp[i][j + k - 1] += res * (j + k) * (j + k - 1);
dp[i][j + k] %= MOD;
dp[i][j + k + 1] %= MOD;
dp[i][j + k - 1] %= MOD;
}
cout << dp[n][1] << endl;
return 0;
}