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

27 篇文章 0 订阅
16 篇文章 1 订阅

Train Problem II
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 10670 Accepted Submission(s): 5717

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 several test cases. Each test cases consists of a number N(1<=N<=100). The input is terminated by the end of file.

Output
For each test case, you should output how many ways that all the trains can get out of the railway.

Sample Input
1
2
3
10

Sample Output
1
2
5
16796

Hint
The result will be very large, so you may not process it by 32-bit integers

[分析]
算几个就知道是卡特兰数了
公式:h(n)=C(2n,n)/(n+1)

就要用组合数,再次复习组合数矩阵
矩阵公式:c[i][j]=c[i-1][j-1]+c[i-1][j];

然后比较需要注意的是要用大数。

核心在main函数,前面都是模版。

[代码]

#include<stack>
#include <algorithm> // max  
#include <cassert>   // assert  
#include <cstdio>    // printf,sprintf  
#include <cstring>   // strlen  
#include <iostream>  // cin,cout  
#include <string>    // string类  
#include <vector>    // vector类  
using namespace std;

struct BigInteger {
    typedef unsigned long long LL;

    static const int BASE = 100000000;
    static const int WIDTH = 8;
    vector<int> s;

    BigInteger& clean() { while (!s.back() && s.size()>1)s.pop_back(); return *this; }
    BigInteger(LL num = 0) { *this = num; }
    BigInteger(string s) { *this = s; }
    BigInteger& operator = (long long num) {
        s.clear();
        do {
            s.push_back(num % BASE);
            num /= BASE;
        } while (num > 0);
        return *this;
    }
    BigInteger& operator = (const string& str) {
        s.clear();
        int x, len = (str.length() - 1) / WIDTH + 1;
        for (int i = 0; i < len; i++) {
            int end = str.length() - i*WIDTH;
            int start = max(0, end - WIDTH);
            sscanf(str.substr(start, end - start).c_str(), "%d", &x);
            s.push_back(x);
        }
        return (*this).clean();
    }

    BigInteger operator + (const BigInteger& b) const {
        BigInteger c; c.s.clear();
        for (int i = 0, g = 0; ; i++) {
            if (g == 0 && i >= s.size() && i >= b.s.size()) break;
            int x = g;
            if (i < s.size()) x += s[i];
            if (i < b.s.size()) x += b.s[i];
            c.s.push_back(x % BASE);
            g = x / BASE;
        }
        return c;
    }
    BigInteger operator - (const BigInteger& b) const {
        assert(b <= *this); // 减数不能大于被减数  
        BigInteger c; c.s.clear();
        for (int i = 0, g = 0; ; i++) {
            if (g == 0 && i >= s.size() && i >= b.s.size()) break;
            int x = s[i] + g;
            if (i < b.s.size()) x -= b.s[i];
            if (x < 0) { g = -1; x += BASE; }
            else g = 0;
            c.s.push_back(x);
        }
        return c.clean();
    }
    BigInteger operator * (const BigInteger& b) const {
        int i, j; LL g;
        vector<LL> v(s.size() + b.s.size(), 0);
        BigInteger c; c.s.clear();
        for (i = 0; i<s.size(); i++) for (j = 0; j<b.s.size(); j++) v[i + j] += LL(s[i])*b.s[j];
        for (i = 0, g = 0; ; i++) {
            if (g == 0 && i >= v.size()) break;
            LL x = v[i] + g;
            c.s.push_back(x % BASE);
            g = x / BASE;
        }
        return c.clean();
    }
    BigInteger operator / (const BigInteger& b) const {
        assert(b > 0);  // 除数必须大于0  
        BigInteger c = *this;       // 商:主要是让c.s和(*this).s的vector一样大  
        BigInteger m;               // 余数:初始化为0  
        for (int i = s.size() - 1; i >= 0; i--) {
            m = m*BASE + s[i];
            c.s[i] = bsearch(b, m);
            m -= b*c.s[i];
        }
        return c.clean();
    }
    BigInteger operator % (const BigInteger& b) const { //方法与除法相同  
        BigInteger c = *this;
        BigInteger m;
        for (int i = s.size() - 1; i >= 0; i--) {
            m = m*BASE + s[i];
            c.s[i] = bsearch(b, m);
            m -= b*c.s[i];
        }
        return m;
    }
    // 二分法找出满足bx<=m的最大的x  
    int bsearch(const BigInteger& b, const BigInteger& m) const {
        int L = 0, R = BASE - 1, x;
        while (1) {
            x = (L + R) >> 1;
            if (b*x <= m) { if (b*(x + 1)>m) return x; else L = x; }
            else R = x;
        }
    }
    BigInteger& operator += (const BigInteger& b) { *this = *this + b; return *this; }
    BigInteger& operator -= (const BigInteger& b) { *this = *this - b; return *this; }
    BigInteger& operator *= (const BigInteger& b) { *this = *this * b; return *this; }
    BigInteger& operator /= (const BigInteger& b) { *this = *this / b; return *this; }
    BigInteger& operator %= (const BigInteger& b) { *this = *this % b; return *this; }

    bool operator < (const BigInteger& b) const {
        if (s.size() != b.s.size()) return s.size() < b.s.size();
        for (int i = s.size() - 1; i >= 0; i--)
            if (s[i] != b.s[i]) return s[i] < b.s[i];
        return false;
    }
    bool operator >(const BigInteger& b) const { return b < *this; }
    bool operator<=(const BigInteger& b) const { return !(b < *this); }
    bool operator>=(const BigInteger& b) const { return !(*this < b); }
    bool operator!=(const BigInteger& b) const { return b < *this || *this < b; }
    bool operator==(const BigInteger& b) const { return !(b < *this) && !(b > *this); }
};

ostream& operator << (ostream& out, const BigInteger& x) {
    out << x.s.back();
    for (int i = x.s.size() - 2; i >= 0; i--) {
        char buf[20];
        sprintf(buf, "%08d", x.s[i]);
        for (int j = 0; j < strlen(buf); j++) out << buf[j];
    }
    return out;
}

istream& operator >> (istream& in, BigInteger& x) {
    string s;
    if (!(in >> s)) return in;
    x = s;
    return in;
}



BigInteger c[210][210];
int main()
{
    c[0][0] = 1;
    for (int i = 1; i < 210; i++)
    {
        c[i][0] = 1; c[i][i] = 1;
        for (int j = 1; j <i; j++)
        {
            c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
        }
    }
    int n;
    while (scanf("%d", &n) != EOF)
    {
        cout << c[2 * n][n] / (n + 1) << endl;
    }
}


//h[n]=c[2*n][n]/(n+1)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值