UVa 10007 & hdu 1131 Count the Trees (卡特兰数)

Count the Trees

Time Limit:3000MS    Memory Limit:0KB    
64bit IO Format:%lld & %llu

SubmitStatus

Description

 Count the Trees 

Another common social inability is known as ACM (Abnormally Compulsive Meditation). This psychological disorder is somewhat common among programmers. It can be described as the temporary (although frequent) loss of the faculty of speech when the whole power
of the brain is applied to something extremely interesting or challenging.

Juan is a very gifted programmer, and has a severe case of ACM (he even participated in an ACM world championship a few months ago). Lately, his loved ones are worried about him, because he has found a new exciting problem to exercise his intellectual powers,
and he has been speechless for several weeks now. The problem is the determination of the number of different labeled binary trees that can be built using exactlyn different elements.

For example, given one element A, just one binary tree can be formed (usingA as the root of the tree). With two elements,
A and B, four different binary trees can be created, as shown in the figure.

If you are able to provide a solution for this problem, Juan will be able to talk again, and his friends and family will be forever grateful.

Input

The input will consist of several input cases, one per line. Each input case will be specified by the numbern (
1 ≤ n ≤ 300 ) of different elements that must be used to form the trees. A number0 will mark the end of input and is not to be processed.

Output

For each input case print the number of binary trees that can be built using the
n
elements, followed by a newline character.

Sample Input

1
2
10
25
0

Sample Output

1
4
60949324800
75414671852339208296275849248768000000

题意:给你n个点,问能够构成多少种不同的树。

解析:卡特兰数。

AC代码:

#include<cstdio>
#include<cstring>
#define SIZE 200
#define MAXN 302
#define BASE 10000

using namespace std;

int Canlan[MAXN][SIZE];
int temp[SIZE];

void A(int n)
{
    memcpy(temp, Canlan[n], sizeof(temp));
    int  e = 0;
    for(int fac = n; fac>0; --fac)
    {
        for(int i = SIZE-1, remain = 0; i>=0; --i)
        {
            e = temp[i] * fac + remain;
            temp[i] = e % BASE;
            remain = e / BASE;
        }
    }
    memcpy(Canlan[n], temp, sizeof(int)*SIZE);
}

void multiply(int elem)
{
    for(int i=SIZE-1, remain = 0; i >= 0; --i)
    {
        remain = temp[i] * elem + remain;
        temp[i] = remain % BASE;
        remain = remain / BASE;
    }
    return;
}

void divide(int elem)
{
    int i;
    for(i=0; i<SIZE && temp[i] == 0; i++);
    for(int remain = 0; i < SIZE; ++i)
    {
        remain += temp[i];
        temp[i] = remain / elem;
        remain = (remain % elem) * BASE;
    }
    return;
}

void Cantalan()
{
    memset(Canlan[1], 0, sizeof(int)*SIZE);
    Canlan[1][SIZE-1] = 1;
    for(int i=2; i<MAXN; ++i)
    {
        memcpy(temp, Canlan[i-1], sizeof(int)*SIZE);
        multiply(4*i-2);
        divide(i+1);
        memcpy(Canlan[i], temp, sizeof(int)*SIZE);
    }
    return;
}

int main()
{
    int n;
    Cantalan();
    for(int i=1; i<MAXN; ++i) A(i);
    while(scanf("%d", &n) != EOF && n)
    {
        int i;
        for(i=0; i<SIZE && Canlan[n][i] == 0; i++);
        printf("%d", Canlan[n][i]);
        if(i+1 == SIZE)
        {
            printf("\n");
            continue;
        }
        for(i=i+1; i<SIZE; ++i)
            printf("%04d", Canlan[n][i]);
        printf("\n");
    }
    return 0;
}
时间: 2024-08-04 10:06:38

UVa 10007 & hdu 1131 Count the Trees (卡特兰数)的相关文章

HDU 1131 Count the Trees 大数计算

题目是说给出一个数字,然后以1到这个数为序号当做二叉树的结点,问总共有几种组成二叉树的方式.这个题就是用卡特兰数算出个数,然后因为有编号,不同的编号对应不同的方式,所以结果是卡特兰数乘这个数的阶乘种方案.因为数字比较大,所以要用高精度的方法也就是用字符数组来做,我分别写了三个函数,一个算加法,一个算乘法,最后一个打表,等打出表来最后只要判断一下输入的数是第几个,直接输出就行了,下面是我的代码,第一次写高精度的这种大数处理,可能看上去比较繁琐= = #include<iostream> #inc

hdu 1131 Count the Trees

卡特兰数*阶乘就是答案     第一次用java..高精度写起来好快....不过代码比较丑.. import java.math.BigInteger; import java.util.Scanner; public class Main { public static void main(String []args) { Scanner cin = new Scanner(System.in); int i,ii; BigInteger []c= new BigInteger[105]; B

hdu 5177 (1e18范围的卡特兰数)

hdu 5177 (1e18范围的卡特兰数) 题意: 求第n个卡特兰数,模3814697265625 (5^18) 限制: 有20组数据,1 <= n <= 1e18 思路: 1. 卡特兰数的表达式: ans = 1/(n+1) * C(2*n,n) -> ans = 1/(n+1) * (2n)! / n! / n!    ---1式 2. 因为要模5^18,求逆元要求互质,所以先把"1式"中的因子5全部去掉 3. 然后看不含因子5的阶乘,f(n!) 4. 设g(x

uva 1478 - Delta Wave(递推+大数+卡特兰数+组合数学)

题目链接:uva 1478 - Delta Wave 题目大意:对于每个位置来说,可以向上,水平,向下,坐标不能位负,每次上下移动最多为1, 给定n问说有多少种不同的图.结果对10100取模. 解题思路:因为最后都要落回y=0的位置,所以上升的次数和下降的次数是相同的,并且上升下降的关系满足出栈入栈的关系.即卡特兰数. 所以每次枚举i,表示有i个上升,i个下降,用组合数学枚举出位置,然后累加求和. C(2?in)?f(i)=C(2?i?2n)?f(i?1)?(n?2?i+1)?(n?2?i+2)

hdu 1130How Many Trees?(卡特兰数)

卡特兰数又称卡塔兰数,英文名Catalan number,是组合数学中一个常出现在各种计数问题中出现的数列. 以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)的名字来命名,其前几项为(从第零项开始) : 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 656412042

HDU Train Problem II (卡特兰数+大数)

Problem Description As we all know the Train Problem I, the boss of the Ignatius Train Station want to know if all the trains come in strict-increasing order, how many orders that all the trains can get out of the railway.   Input The input contains

HDU 1133 Buy the Ticket 卡特兰数

设50元的人为+1 100元的人为-1 满足前任意k个人的和大于等于0 卡特兰数 C(n+m, m)-C(n+m, m+1)*n!*m! import java.math.*; import java.util.*; public class Main { /** * @param args */ public static void main(String[] args) { Scanner sc = new Scanner(System.in); int cas = 1; while(tru

HDU 1023 Train Problem II (卡特兰数,经典)

题意:给出一个数字n,假设火车从1~n的顺序分别进站,求有多少种出站序列. 思路:卡特兰数的经典例子.n<101,用递推式解决.需要使用到大数.n=100时大概有200位以下. 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=101; 4 vector<string> vect; 5 void _mult(string num1, string num2, string &result )

hdu 3723 Card Game(JAVA,卡特兰数)

很容易想到的卡特兰数,不过复杂度高精度还是挺恶心的. 于是用JAVA秒杀了. import java.math.BigInteger; import java.util.Scanner; public class Main { static BigInteger[] f=new BigInteger[5005]; static BigInteger[] c=new BigInteger[10005]; static BigInteger MOD; static void init(){ f[0]