zoukankan      html  css  js  c++  java
  • HDU ACM 1134 Game of Connections / 1130 How Many Trees?(卡特兰数)

    【题目链接】http://acm.hdu.edu.cn/showproblem.php?pid=1134

    【解题背景】这题不会做,自己推公式推了一段时间,将n=3和n=4的情况列出来了,只发现第n项与第n-1项有关系,上网搜索的时候发现是组合数学中关于Catalan(卡特兰)数的运用.

    以下资料来自网络,整理以备记录学习:

    【来源链接】

    http://baike.baidu.com/view/2499752.htm

    http://blog.163.com/lz_666888/blog/static/1147857262009914112922803/

    Catalan序列是一个整数序列,其通项公式是   我们从中取出的Cn就叫做第 n 个 Catalan 数,前17个 Catalan 数分别是:

    1,  1,  2,  5,  14,  42,  132,  429,  1430,  4862,  16796,  58786,  208012,  742900,  2674440,  9694845,  35357670

    令h(0) = 1,h(1) = 1,catalan 数满足递推式:

    h(n) = h(0)*h(n-1) + h(1)*h(n-2) + ... + h(n-1)*h(0) (n>=2)

    另类递归式:

    h(n)=((4*n-2)/(n+1))*h(n-1);

    该递推关系的解为:

    h(n+1)=C(2n,n)/(n+1) (n=1,2,3,...)

    Catalan序列主要有几类运用:

    1.括号化问题:

    矩阵链乘: P=a1×a2×a3×……×an,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?(h(n-1)种)

    2.出栈次序问题:

    一个栈(无穷大)的进栈序列为1,2,3,..n,有多少个不同的出栈序列?

    类似:有2n个人排成一行进入剧场。入场费5元。其中只有n个人有一张5元钞票,另外n人只有10元钞票,剧院无其它钞票,问有多少中方法使得只要有10元的人买票,售票处就有5元的钞票找零?(将持5元者到达视作将5元入栈,持10元者到达视作使栈中某5元出栈)

    3.将多边行划分为三角形问题:

    将一个凸多边形区域分成三角形区域的方法数?

    类似:在圆上选择2n个点,将这些点成对连接起来使得所得到的n条线段不相交的方法数?(也就是本题)

    4.给顶节点组成二叉树的问题:

    给定n个节点,能构成多少种不同的二叉树?

    (能构成h(n)个,这个公式的下标是从h(0)=1开始的)

     【随笔:本来知道这个公式之后想打表打出100个Catalan数,将公式化简了一下且用代码尝试了一下:

    1         if(n == 1 || n == 2){
    2             printf("1
    ");
    3             continue;
    4         }
    5         int sum = 1;
    6         for(int t=2*n-1; t>n+1; t-=2)
    7             sum *= t;
    8         //func(int m)函数求m的阶乘,func_pow(int a, int b) 函数求a的b次方 
    9         printf("%d
    ", sum*func_pow(2, n/2)/func(n/2+n%2));

    后来发现这也是大数处理的问题,翻看之前自己写的大数相乘大数相除的代码,发现写的很吃力,干脆上网找大数处理的若干代码,发现可以很简单的进行大数相乘及大数相除,即为现在的Ac源代码中的大数处理

    源码来自:http://blog.163.com/lz_666888/blog/static/1147857262009914112922803/

     1 #include<iostream>
     2 #define MAX 100
     3 #define BASE 10000
     4 
     5 using namespace std;
     6 
     7 void multiply(int a[],int Max,int b) //大数乘法,注意参数的传递
     8 {
     9     int i,array=0;
    10     for (i = Max-1; i >= 0; i--)
    11     {
    12         array += b * a[i];
    13         a[i] = array % BASE; // 数组每一位存放大数的四位数字
    14         array /= BASE;   
    15     }
    16     return;
    17 }
    18 
    19 void divide(int a[], int Max, int b) //模拟大数除法
    20 {
    21     int i, div = 0;
    22     for (i = 0; i < Max; i++)   
    23     {
    24         div = div * BASE + a[i];
    25         a[i] = div / b;
    26         div %= b;
    27     }
    28 }
    29 int main()
    30 {
    31     int a[101][MAX],i, n;
    32     memset(a[1],0,MAX*sizeof(int));
    33     for (i=2, a[1][MAX-1] = 1; i < 101; i++) // 高坐标存放大数低位
    34     {
    35         memcpy(a[i], a[i-1], MAX * sizeof(int));      //h[i] = h[i-1];
    36         multiply(a[i], MAX, 4 * i - 2);               //h[i] *= (4*i-2);
    37         divide(a[i], MAX, i + 1);                  //h[i] /= (i+1);
    38     }
    39     while (cin >> n && n != -1)   
    40     {
    41         for (i = 0; i < MAX && a[n][i] == 0; i++); //去掉数组前为0的数字。
    42         cout << a[n][i++];             //输出第一个非0数
    43         for (; i < MAX; i++)   
    44         {
    45             printf("%04d",a[n][i]);       //输出后面的数,并每位都保持4位长度!(32767)
    46            }
    47         cout << endl;
    48     }
    49     return 0;
    50 }
  • 相关阅读:
    HDU 3401 Trade
    POJ 1151 Atlantis
    HDU 3415 Max Sum of MaxKsubsequence
    HDU 4234 Moving Points
    HDU 4258 Covered Walkway
    HDU 4391 Paint The Wall
    HDU 1199 Color the Ball
    HDU 4374 One hundred layer
    HDU 3507 Print Article
    GCC特性之__init修饰解析 kasalyn的专栏 博客频道 CSDN.NET
  • 原文地址:https://www.cnblogs.com/liaoguifa/p/3203329.html
Copyright © 2011-2022 走看看