Game of Connections -組合數學中的計數問題

問題描述:

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<

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章