SPOJ

来源:互联网 发布:中国人才流失严重知乎 编辑:程序博客网 时间:2024/05/01 21:05

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;}
原创粉丝点击