Make Triangle
分类:数学
1.题意概述
- 给出一个凸n边形,问用n-3条不相交的对角线将该n边形划分为三角形的方案数?
2.解题思路
卡特兰数:
- h(n)=h(0)⋅h(n−1)+h(1)⋅h(n−2)+...+h(n−1)⋅h(0) , n≥2
- 另类递推式:
- h(n)=(4n−2)⋅h(n−1)n+1
递推:因为凸多边形的任意一条边必定属于某一个三角形,所以我们以某一条边为基准,以这条边的两个顶点为起点 P1 和终点 Pn ,将该凸多边形的顶点依序标记为 P1、P2...Pn ,再在该凸多边形中找任意一个不属于这两个点的顶点 Pk(2≤k≤n−1) ,来构成一个三角形,用这个三角形把一个凸多边形划分成两个凸多边形,其中一个凸多边形,是由 P1,P2…Pk 构成的凸 k 边形(顶点数即是边数),另一个凸多边形,是由
Pk,Pk+1…Pn 构成的凸 (n−k+1) 边形。此时,我们若把 Pk 视为确定一点,那么根据乘法原理, f(n) 的问题就等价于——凸 k 多边形的划分方案数乘以凸
(n−k+1) 多边形的划分方案数,即选择 Pk 这个顶点有 f(n)=f(k)×f(n−k+1) 。而k可以从2到n-1,所以再根据加法原理,将k取不同值的划分方案相加,得到的总方案数为: f(n)=f(2)×f(n−2+1)+f(3)×f(n−3+1)+…+f(n−1)×f(2) 。到此处,再看看卡特兰数的递推式,答案不言而喻,即为 f(n)=h(n−2), n=2,3,4…… 。最后,令 f(2)=1,f(3)=1 。但是答案要取模 (105+7) 这不是一个质数,(i+1)的逆元也不好求,所以我们考虑前一种递推式。
3.AC代码
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 100100
#define lson root << 1
#define rson root << 1 | 1
#define N 1001
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e5 + 7;
typedef long long ll;
typedef unsigned long long ull;
ll dp[N];
void solve()
{
dp[2] = dp[3] = 1;
dp[4] = 2;
for (int i = 4; i <= N; i++)
{
ll temp = 0;
for (int j = 2; j < i; j++)
temp = (temp + dp[i - j + 1] * dp[j]) % mod;
dp[i] = temp;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
long _begin_time = clock();
#endif
int t;
solve();
scanf("%d", &t);
while (t--)
{
int n;
scanf("%d", &n);
printf("%lld\n", dp[n]);
}
#ifndef ONLINE_JUDGE
long _end_time = clock();
printf("time = %ld ms.", _end_time - _begin_time);
#endif
return 0;
}