• 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 }
  • 相关阅读:
    Google Maps API 进级:通过XML文档加载Gpolyline或者Gpolygon
    Google Maps API 进级: GPolygon对象2
    Google Maps API 进级: GoogleMaps常用事件及应用思路2
    debian下安装JDK
    sudo 提示用户不在sudoers文件错误
    debian关闭开机自动启动时候的gui
    debian解决中文乱码,安装chinese font
    debian下intel 3945abg和T420无线网卡驱动
    debian修改系统时区
    wheezy安装oracle jdk的jdk之中文乱码处理
  • 原文地址:https://www.cnblogs.com/liaoguifa/p/3203329.html
Copyright © 2020-2023  润新知