2 条题解
-
0
递推写法
#include <bits/stdc++.h> #define int long long using namespace std; const int MAXN = 2000; const int MOD = 1'000'000'000 + 7; // 求 n 个点,m 层的 AVL 树有多少种 // 实际上 m 是 log n 的级别 int f[MAXN + 5][MAXN + 5]; // 求 n 个点的 AVL 树有多少种 int book[MAXN + 5]; signed main() { ios::sync_with_stdio(false); cin.tie(0); f[0][0] = 1; // 节点个数 for (int n = 1; n <= 2000; n++) { // 层数,某个层树可行但多一层不可行时就不用算了。 for (int m = 1; m <= 2000; m++) { // 左子树节点个数 for (int i = 0; i <= n - 1; i++) { int j = (n - 1) - i; f[n][m] += f[i][m - 1] * f[j][m - 1] % MOD; if (m >= 2) { f[n][m] += f[i][m - 1] * f[j][m - 2] % MOD; f[n][m] += f[i][m - 2] * f[j][m - 1] % MOD; } f[n][m] %= MOD; } if (f[n][m - 1] && !f[n][m]) break; book[n] += f[n][m]; book[n] %= MOD; } } int n; while (cin >> n) cout << book[n] << "\n"; return 0; }
-
0
记忆化写法
#include <bits/stdc++.h> #define int long long using namespace std; const int MAXN = 2000; const int MOD = 1'000'000'000 + 7; // 求 n 个点,m 层的 AVL 树有多少种 // 实际上 m 是 log n 的级别 int f[MAXN + 5][MAXN + 5]; // 懒得初始化 f 了,单独开一个判断有没有记忆过 bool vis[MAXN + 5][MAXN + 5]; int cal(int n, int m) { if (vis[n][m]) return f[n][m]; vis[n][m] = true; if (m == 0) return f[n][m] = (n == 0); // 左边节点数量 int res = 0; for (int i = 0; i <= n - 1; i++) { int j = (n - 1) - i; // 右边节点数量 if (m >= 2) { res += cal(i, m - 1) * cal(j, m - 2) % MOD; res += cal(i, m - 2) * cal(j, m - 1) % MOD; } res += cal(i, m - 1) * cal(j, m - 1) % MOD; res %= MOD; } return f[n][m] = res; } // 求 n 个点的 AVL 树有多少种 int book[MAXN + 5]; int work(int n) { if (book[n]) return book[n]; int res = 0; int pre = 0; for (int i = 1; i <= n; i++) { int now = cal(n, i); res += now; res %= MOD; if (pre && !now) break; pre = now; } return book[n] = res; } signed main() { ios::sync_with_stdio(false); cin.tie(0); int n; while (cin >> n) cout << work(n) << "\n"; return 0; }
- 1
信息
- ID
- 13404
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 7
- 标签
- (无)
- 递交数
- 25
- 已通过
- 7
- 上传者