问题描述:
This is a small but ancient game. You are supposed to write down the numbers 1, 2, 3, ... , 2n - 1, 2n consecutively in clockwise order on the ground to form a circle, and then, to draw some straight line segments to connect
them into number pairs. Every number must be connected to exactly one another. And, no two segments are allowed to intersect.
It's still a simple game, isn't it? But after you've written down the 2n numbers, can you tell me in how many different ways can you connect the numbers into pairs? Life is harder, right?
输入:
Each line of the input file will be a single positive number n, except the last line, which is a number -1. You may assume that 1 <= n <= 100.
输出:
For each n, print in a single line the number of ways to connect the 2n numbers into pairs.
输入样例:
2
3
-1
输出样例:
2
5
问题分析:刚开始不知道是卡特兰数,然后画图推了一下:从点1开始顺时针排一个圆,先把顶点为4个的方案画出来,然后画6个的,就会发现如果将点1与2相连或者点1与6相连的时候,剩下四个点的方案就是顶点为4时候的,此时得出的方案数:2*2=4,如果点1与4相连,则2,3与5,6则又是一种方案(顶点为2个的时候)4+1*1,由此推出,将点1与偶数点相连再把点1与偶数点相连分隔出的两边的方案数相乘,则得到答案,附上代码(刚开始WA了两遍还以为自己思路错了,然后去poj上看了一下讨论,copy了一个大整数类,然后就过了哈哈):
#include
using namespace std;
typedef unsigned long long LL;
const int maxn = 200;
struct bign {
int len, s[maxn];
bign() {
memset(s, 0, sizeof(s));
len = 1;
}
bign(int num) {
*this = num;
}
bign(const char* num) {
*this = num;
}
bign operator =(int num) { //直接以整数赋值
char s[maxn];
sprintf(s, "%d", num);
*this = s;
return *this;
}
bign operator =(const char* num) { //以字符串赋值
len = strlen(num);
for(int i = 0; i < len; i++)
s[i] = num[len - i - 1] - '0';
return *this;
}
string str() const { //将bign转化成字符串
string res = "";
for(int i = 0; i < len; i++)
res = (char) (s[i] + '0') + res;
if(res == "")
res = "0";
return res;
}
bign operator +(const bign& b) const { //重载+号运算
bign c;
c.len = 0;
for(int i = 0, g = 0; g || i < max(len, b.len); i++) {
int x = g;
if(i < len) x += s[i];
if(i < b.len) x += b.s[i];
c.s[c.len++] = x % 10;
g = x / 10;
}
return c;
}
void clean() { //去掉前到0
while(len > 1 && !s[len - 1])
len--;
}
bign operator *(const bign& b) { //重载*号运算
bign c;
c.len = len + b.len;
for(int i = 0; i < len; i++)
for(int j = 0; j < b.len; j++)
c.s[i + j] += s[i] * b.s[j];
for(int i = 0; i < c.len - 1; i++) {
c.s[i + 1] += c.s[i] / 10;
c.s[i] %= 10;
}
c.clean();
return c;
}
bign operator -(const bign& b) { //重载-号运算
bign c;
c.len = 0;
for(int i = 0, g = 0; i < len; i++) {
int x = s[i] - g;
if(i < b.len)
x -= b.s[i];
if(x >= 0)
g = 0;
else {
g = 1;
x += 10;
}
c.s[c.len++] = x;
}
c.clean();
return c;
}
bool operator <(const bign& b) const { //重载<号运算
if(len != b.len)
return len < b.len;
for(int i = len - 1; i >= 0; i--)
if(s[i] != b.s[i])
return s[i] < b.s[i];
return false;
}
bool operator >(const bign& b) const { //重载>号运算
return b < *this;
}
bool operator <=(const bign& b) { //重载<=号运算
return !(b > *this);
}
bool operator ==(const bign& b) { //重载>=号运算
return !(b < *this) && !(*this < b);
}
bign operator +=(const bign& b) { //重载+=号运算
*this = *this + b;
return *this;
}
};
istream& operator >>(istream &in, bign& x) { //重载输入运算符
string s;
in >> s;
x = s.c_str();
return in;
}
ostream& operator <<(ostream &out, const bign& x) { //重载输出运算符
out << x.str();
return out;
}
bign a[103];
int main()
{
memset(a,0,sizeof(a));
a[1]=1;
a[2]=2;
int n;
int temp=3;
for(int i=3; i<=100; i++)
{
a[i]=0;
for(int j=2; j<=i; j++)
{
a[i]+=a[j-1]*a[i-j];
}
a[i]=a[i]+a[i-1]+a[i-1];
}
while(cin>>n&&n>0)
{
cout<