HDU 1134 Game of Connections(卡特兰数)

题目代号:HDU 1134

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1134

Game of Connections

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4668    Accepted Submission(s):
2729

Problem 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

题目大意:给出一个值n(n<=100),1,2,3,···2n围成一个圈,问有多少种方式让每个数字成对连接的同时不相交。因为数据非常大,所以我选择先用大数模板算出卡特兰数的前一百个数据之后打表。

打表代码:

# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <iostream>
# include <fstream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <math.h>
# include <algorithm>
using namespace std;
# define pi acos(-1.0)
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define For(i,n,a) for(int i=n; i>=a; --i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define Fo(i,n,a) for(int i=n; i>a ;--i)
typedef long long LL;
typedef unsigned long long ULL;

string num[105]={"1","1"};

//string比较函数:相等返回0,str1>str2返回1,str1<str2返回-1.
int Compare(string str1,string str2)
{
    if(str1.length() > str2.length()) return 1;
    else if(str1.length() < str2.length()) return -1;
    else return str1.compare(str2);
}

string Big_Plus(string str1,string str2)
{
    string ans;
    int len1=str1.length();
    int len2=str2.length();
    //将长度较小的前面补0,使两个string长度相同
    if(len1<len2){
        for(int i=1;i<=len2-len1;i++){
            str1="0"+str1;
        }
    }else {
        for(int i=1;i<=len1-len2;i++){
            str2="0"+str2;
        }
    }
    int len=max(len1,len2);
    int carry=0;
    for(int i=len-1;i>=0;i--){
        int tmp=str1[i]-‘0‘+str2[i]-‘0‘+carry;
        carry=tmp/10;
        tmp%=10;
        ans=char(tmp+‘0‘)+ans;
    }
    if(carry) ans=char(carry+‘0‘)+ans;
    return ans;
}

//支持大数减小数
string Big_Sub(string str1,string str2)
{
    string ans;
    int carry=0;
    int difference=str1.length()-str2.length();//长度差
    for(int i=str2.length()-1;i>=0;i--){
        if(str1[difference+i]<str2[i]+carry){
            ans=char(str1[difference+i]+10-str2[i]-carry+‘0‘)+ans;
            carry=1;
        }else {
            ans=char(str1[difference+i]-str2[i]-carry+‘0‘)+ans;
            carry=0;
        }
    }
    for(int i=difference-1;i>=0;i--){
        if(str1[i]-carry>=‘0‘){
            ans=char(str1[i]-carry)+ans;
            carry=0;
        }else {
            ans=char(str1[i]-carry+10)+ans;
            carry=1;
        }
    }
    //去除前导0
    ans.erase(0,ans.find_first_not_of(‘0‘));
    if(ans.empty()) ans="0";
    return ans;
}

string Big_Mul(string str1,string str2)
{
    string ans;
    int len1=str1.length();
    int len2=str2.length();
    for(int i=len2-1;i>=0;i--){
        string tmpstr="";
        int data=str2[i]-‘0‘;
        int carry=0;
        if(data!=0){
            for(int j=1;j<=len2-1-i;j++){
                tmpstr+="0";
            }
            for(int j=len1-1;j>=0;j--){
                int t=data*(str1[j]-‘0‘)+carry;
                carry=t/10;
                t%=10;
                tmpstr=char(t+‘0‘)+tmpstr;
            }
            if(carry!=0) tmpstr=char(carry+‘0‘)+tmpstr;
        }
        ans=Big_Plus(ans,tmpstr);
    }
    ans.erase(0,ans.find_first_not_of(‘0‘));
    if(ans.empty()) ans="0";
    return ans;
}

//正数相除,商为quotient,余数为residue

void Big_Div(string str1,string str2,string& quotient,string& residue)
{
    quotient=residue="";//商和余数清空
    if(str2=="0"){//;判断除数是否为0
        quotient=residue="ERROR";
        return;
    }
    if(str1=="0"){//判断被除数是否为0
        quotient=residue="0";
        return;
    }
    int res=Compare(str1,str2);
    if(res<0){//被除数小于除数
        quotient="0";
        residue=str1;
        return;
    }else if(res==0){
        quotient="1";
        residue="0";
        return ;
    }else {
        int len1=str1.length();
        int len2=str2.length();
        string tmpstr;
        tmpstr.append(str1,0,len2-1);//将str1的前len2位赋给tmpstr
        for(int i=len2-1;i<len1;i++){
            tmpstr=tmpstr+str1[i];//被除数新补充一位
            tmpstr.erase(0,tmpstr.find_first_not_of(‘0‘));//去除前导0
            if(tmpstr.empty()) tmpstr="0";
            for(char ch=‘9‘;ch>=‘0‘;ch--){//试商
                string tmp,ans;
                tmp=tmp+ch;
                ans=Big_Mul(str2,tmp);//计算乘积
                if(Compare(ans,tmpstr)<=0){//试商成功
                    quotient=quotient+ch;
                    tmpstr=Big_Sub(tmpstr,ans);//减掉乘积
                    break;
                }
            }
        }
        residue=tmpstr;
    }
    quotient.erase(0,quotient.find_first_not_of(‘0‘));
    if(quotient.empty()) quotient="0";
}

int main()
{
    int n;
    for(int i=0;i<=100;i++)
    {
        if(i>1)for(int j=0;j<i;j++)
        {
            num[i]=Big_Plus(Big_Mul(num[j],num[i-j-1]),num[i]);
        }
        cout<<"\""<<num[i]<<"\","<<endl;
    }
    return 0;
}

  

打表完成后的代码很容易:

# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <iostream>
# include <fstream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <math.h>
# include <algorithm>
using namespace std;
# define pi acos(-1.0)
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define For(i,n,a) for(int i=n; i>=a; --i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define Fo(i,n,a) for(int i=n; i>a ;--i)
typedef long long LL;
typedef unsigned long long ULL;

string num[105]= {"1",
                  "1",
                  "2",
                  "5",
                  "14",
                  "42",
                  "132",
                  "429",
                  "1430",
                  "4862",
                  "16796",
                  "58786",
                  "208012",
                  "742900",
                  "2674440",
                  "9694845",
                  "35357670",
                  "129644790",
                  "477638700",
                  "1767263190",
                  "6564120420",
                  "24466267020",
                  "91482563640",
                  "343059613650",
                  "1289904147324",
                  "4861946401452",
                  "18367353072152",
                  "69533550916004",
                  "263747951750360",
                  "1002242216651368",
                  "3814986502092304",
                  "14544636039226909",
                  "55534064877048198",
                  "212336130412243110",
                  "812944042149730764",
                  "3116285494907301262",
                  "11959798385860453492",
                  "45950804324621742364",
                  "176733862787006701400",
                  "680425371729975800390",
                  "2622127042276492108820",
                  "10113918591637898134020",
                  "39044429911904443959240",
                  "150853479205085351660700",
                  "583300119592996693088040",
                  "2257117854077248073253720",
                  "8740328711533173390046320",
                  "33868773757191046886429490",
                  "131327898242169365477991900",
                  "509552245179617138054608572",
                  "1978261657756160653623774456",
                  "7684785670514316385230816156",
                  "29869166945772625950142417512",
                  "116157871455782434250553845880",
                  "451959718027953471447609509424",
                  "1759414616608818870992479875972",
                  "6852456927844873497549658464312",
                  "26700952856774851904245220912664",
                  "104088460289122304033498318812080",
                  "405944995127576985730643443367112",
                  "1583850964596120042686772779038896",
                  "6182127958584855650487080847216336",
                  "24139737743045626825711458546273312",
                  "94295850558771979787935384946380125",
                  "368479169875816659479009042713546950",
                  "1440418573150919668872489894243865350",
                  "5632681584560312734993915705849145100",
                  "22033725021956517463358552614056949950",
                  "86218923998960285726185640663701108500",
                  "337485502510215975556783793455058624700",
                  "1321422108420282270489942177190229544600",
                  "5175569924646105559418940193995065716350",
                  "20276890389709399862928998568254641025700",
                  "79463489365077377841208237632349268884500",
                  "311496878311103321137536291518809134027240",
                  "1221395654430378811828760722007962130791020",
                  "4790408930363303911328386208394864461024520",
                  "18793142726809884575211361279087545193250040",
                  "73745243611532458459690151854647329239335600",
                  "289450081175264899454283846029490767264392230",
                  "1136359577947336271931632877004667456667613940",
                  "4462290049988320482463241297506133183499654740",
                  "17526585015616776834735140517915655636396234280",
                  "68854441132780194707888052034668647142985206100",
                  "270557451039395118028642463289168566420671280440",
                  "1063353702922273835973036658043476458723103404520",
                  "4180080073556524734514695828170907458428751314320",
                  "16435314834665426797069144960762886143367590394940",
                  "64633260585762914370496637486146181462681535261000",
                  "254224158304000796523953440778841647086547372026600",
                  "1000134600800354781929399250536541864362461089950800",
                  "3935312233584004685417853572763349509774031680023800",
                  "15487357822491889407128326963778343232013931127835600",
                  "60960876535340415751462563580829648891969728907438000",
                  "239993345518077005168915776623476723006280827488229600",
                  "944973797977428207852605870454939596837230758234904050",
                  "3721443204405954385563870541379246659709506697378694300",
                  "14657929356129575437016877846657032761712954950899755100",
                  "57743358069601357782187700608042856334020731624756611000",
                  "227508830794229349661819540395688853956041682601541047340",
                  "896519947090131496687170070074100632420837521538745909320",
                 };

int main()
{
    int n;
    while(cin>>n,n!=-1)
    {
        cout<<num[n]<<endl;
    }
    return 0;
}

  

时间: 2024-10-11 01:01:00

HDU 1134 Game of Connections(卡特兰数)的相关文章

hdu 5177 (1e18范围的卡特兰数)

hdu 5177 (1e18范围的卡特兰数) 题意: 求第n个卡特兰数,模3814697265625 (5^18) 限制: 有20组数据,1 <= n <= 1e18 思路: 1. 卡特兰数的表达式: ans = 1/(n+1) * C(2*n,n) -> ans = 1/(n+1) * (2n)! / n! / n!    ---1式 2. 因为要模5^18,求逆元要求互质,所以先把"1式"中的因子5全部去掉 3. 然后看不含因子5的阶乘,f(n!) 4. 设g(x

POJ2084 Game of Connections 卡特兰数 关于卡特兰数经典的几个问题

Game of Connections Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 9128   Accepted: 4471 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 ord

HDU 1133 Buy the Ticket 卡特兰数

设50元的人为+1 100元的人为-1 满足前任意k个人的和大于等于0 卡特兰数 C(n+m, m)-C(n+m, m+1)*n!*m! import java.math.*; import java.util.*; public class Main { /** * @param args */ public static void main(String[] args) { Scanner sc = new Scanner(System.in); int cas = 1; while(tru

HDU 1023 Train Problem II (卡特兰数,经典)

题意:给出一个数字n,假设火车从1~n的顺序分别进站,求有多少种出站序列. 思路:卡特兰数的经典例子.n<101,用递推式解决.需要使用到大数.n=100时大概有200位以下. 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=101; 4 vector<string> vect; 5 void _mult(string num1, string num2, string &result )

hdu 3723 Card Game(JAVA,卡特兰数)

很容易想到的卡特兰数,不过复杂度高精度还是挺恶心的. 于是用JAVA秒杀了. import java.math.BigInteger; import java.util.Scanner; public class Main { static BigInteger[] f=new BigInteger[5005]; static BigInteger[] c=new BigInteger[10005]; static BigInteger MOD; static void init(){ f[0]

B - 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. E

POJ 2084 Game of Connections 卡特兰数

看了下大牛们的,原来这题是卡特兰数,顺便练练java.递归式子:h(0)=1,h(1)=1   h(n)= h(0)*h(n-1) + h(1)*h(n-2) + ... + h(n-1)h(0) (其中n>=2)   打表172MS import java.math.BigInteger; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in=new S

HDU Train Problem II (卡特兰数+大数)

Problem Description As we all know the Train Problem I, the boss of the Ignatius Train Station want to know if all the trains come in strict-increasing order, how many orders that all the trains can get out of the railway.   Input The input contains

hdu 1134 Game of Connections 【卡特兰数+大数】

Game of Connections Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3327    Accepted Submission(s): 1896 Problem Description This is a small but ancient game. You are supposed to write down the