Game of Connections
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 8105 | Accepted: 4054 |
Description
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?
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?
Input
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.
You may assume that 1 <= n <= 100.
Output
For each n, print in a single line the number of ways to connect the 2n numbers into pairs.
Sample Input
2 3 -1
Sample Output
2 5
【分析】
题目考的是卡特兰数, h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2),通过运用大数相乘和大数相加问题实现结果,这里的大数相乘不像之前 的大数相乘,乘一个int型的数,这里的乘是乘一个大数,瞬间难度就上来了,自 己想了很久都没想好怎么实现,看了别人的代码,发现两种实现大数乘大数不错的 方法,现在分享给你~~
【代码】
/*
* catalan数(卡特兰数)满足递推式:
* 1. h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)
* 2. h(n)=h(n-1)*(4*n-2)/(n+1);
* 3. h(n)=C(2n,n)/(n+1) (n=0,1,2,...)
* 4. h(n)=c(2n,n)-c(2n,n-1)(n=0,1,2,...)
*/
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
/* 函数功能:大数相加,不用管大数的长度,其中的大数可以为空*/
string add(string a,string b)//大数加法
{
int i,j,k,flag;
string c;
c="";
i=a.size()-1;j=b.size()-1;
k=0;flag=0;//flag为标记是否要进位
while(i>=0&&j>=0)
{
c+=(a[i]+b[j]-'0'+flag);
//往string类型的字符串加数字子不能像数组那样直接c[k++],会内存错误
flag=0;
if(c[k]>'9')
{
flag=1;
c[k]=c[k]-10;
}
i--;j--;k++; // 从各位加起
}
while(i>=0)
{
c+=(a[i]+flag);
flag=0;
if(c[k]>'9')
{
flag=1;
c[k]=c[k]-10;
}
i--;k++;
}
while(j>=0)
{
c+=b[j]+flag;
flag=0;
if(c[k]>'9')
{
flag=1;
c[k]=c[k]-10;
}
j--;k++;
}
char t;
if(flag)
{
c+=(flag+'0');k++;
}
for(i=0,j=k-1;i<j;i++,j--)
{
t=c[i];c[i]=c[j];c[j]=t; // 大位在前
}
return c;
}
/* 函数功能:大数乘大数 */
/*
memset(ans, 0, sizeof(ans));
for(int i = 0; i < len1; ++i)
a[len1 - i - 1] = s1[i] - '0';
for(int i = 0; i < len2; ++i)
b[len2 - i - 1] = s2[i] - '0';
for(int i = 0; i < len1; ++i)
for(int j = 0; j< len2; ++j)
ans[i + j] += a[i] * b[j];
*/
string mult(string a,string b)//大数乘法
{
int flag=0,i,j,k,p,q,t,max;
char ch;
string c,ans;
p=a.size()-1;q=b.size()-1;
ans="0";
for(i=p;i>=0;i--)//可以分解为p个一位数和一个大数的乘法
{
flag=0;c="";
for(j=i;j<p;j++) c+='0'; // 起到一位数后面的0不能少,千位乘大数时后面有3个0
for(j=q;j>=0;j--)
{
t=(b[j]-'0')*(a[i]-'0')+flag;
flag=t/10;
c+=(t%10+'0'); // c字符串保存着一位数乘大数的结果
}
if(flag) c+=(flag+'0'); // 如果最后进位,就扩展1个单位
for(j=0,k=c.size()-1;j<k;j++,k--)
{
ch=c[j];c[j]=c[k];c[k]=ch; // 反向,位大的在前
}
ans=add(ans,c);
}
return ans;
}
int main()
{
int i,j,n;
string a,ans[101];
ans[0]="1";ans[1]="1";ans[2]="2";ans[3]="5";
for(i=4;i<101;i++)ans[i]="0";
for(i=4;i<101;i++)
{
for(j=0;j<i;j++)
{
a=mult(ans[j],ans[i-j-1]); // h[j]*h[i-j-1]
ans[i]=add(ans[i],a); // h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)
}
}
while(cin>>n&&n!=-1)
{
cout<<ans[n]<<endl;
}
return 0;
}
有什么问题记得留言,么么哒