SPOJ - Make Triangle - 数学

Make Triangle

题目链接

分类:数学

1.题意概述

  • 给出一个凸n边形,问用n-3条不相交的对角线将该n边形划分为三角形的方案数?

2.解题思路

  • 卡特兰数

    • h(n)=h(0)h(n1)+h(1)h(n2)+...+h(n1)h(0) n2
    • 另类递推式:
      • h(n)=(4n2)h(n1)n+1
  • 递推:因为凸多边形的任意一条边必定属于某一个三角形,所以我们以某一条边为基准,以这条边的两个顶点为起点 P1 和终点 Pn ,将该凸多边形的顶点依序标记为 P1P2...Pn ,再在该凸多边形中找任意一个不属于这两个点的顶点 Pk(2kn1) ,来构成一个三角形,用这个三角形把一个凸多边形划分成两个凸多边形,其中一个凸多边形,是由 P1P2Pk 构成的凸 k 边形(顶点数即是边数),另一个凸多边形,是由PkPk+1Pn构成的凸 (nk+1) 边形。

    此时,我们若把 Pk 视为确定一点,那么根据乘法原理, f(n) 的问题就等价于——凸 k 多边形的划分方案数乘以凸(nk+1)多边形的划分方案数,即选择 Pk 这个顶点有 f(n)=f(k)×f(nk+1) 。而k可以从2到n-1,所以再根据加法原理,将k取不同值的划分方案相加,得到的总方案数为: f(n)=f(2)×f(n2+1)+f(3)×f(n3+1)++f(n1)×f(2) 。到此处,再看看卡特兰数的递推式,答案不言而喻,即为 f(n)=h(n2), n=234

    最后,令 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值