画个图,就很好想了
假设圆上有n = 2 * k个点.选定一个点为点1,然后顺时针给其他点编号2,3...n
考虑一下点1应该和哪些点相连,画个图,可以看出,有可能与点1相连的点为2,4,6...n
进一步,假设点1与点p相连了, 那么我们将园分割成了两部分,这两部分包含的点分别为:
2,3,4,5,6,...,p - 1 和 p+1, p+2,....,n
这两部分,可以进一步做分割, 这样子,我们就成功把原问题转化为子问题了, 可以递归解决了.
最后, 为了不TLE, 需要做记忆化的处理。
#include <cstdio>
#include <vector>
#include <cmath>
#include <cassert>
using namespace std;
typedef __int64 int64;
vector<int64> f;
//圆上有n个点, 返回不同的分割方案数
int64 solve(int n) {
if (n == 0) return 1;
if (n == 2) return 1;
if (n == 4) return 2;
if (f[n / 2] != -1) return f[n / 2];
int i;
int64 ans = 0;
for (i = 2; i <= n; i += 2) {
ans = ans + solve(i - 2) * solve(n - i);
}
return f[n/2] = ans;
}
int main() {
int k;
int i;
scanf("%d", &k);
f.resize(k + 2);
for (i = 0; i < f.size(); ++i) f[i] = -1;
for (i = 6; i <= 2 * k; i += 2) {
solve(i);
}
printf("%I64d %d\n", solve(2 * k), k + 1);
return 0;
}