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)