POJ 2084 Game of Connections

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?

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.

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;
}

有什么问题记得留言,么么哒




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值