Game of Connections -组合数学中的计数问题

来源:互联网 发布:解压 mac 编辑:程序博客网 时间:2024/06/14 00:50

问题描述:

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() { //去掉前到0while(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<