题目描述

一列火车n节车厢,依次编号为1,2,3,…,n。每节车厢有两种运动方式,进栈与出栈,问n节车厢出栈的可能排列方式有多少种。

 

输入

一个数,n(n<=60000)

 

输出

一个数s表示n节车厢出栈的可能排列方式
 

题解:

这题要用大数,java

然后卡特兰数:有个数学模型 s[i]=c(n,2n)/(n+1)

组合数公式:这个总是记不住
这个题不能直接求,会TLE。需要先求出结果的每个质因数有多少次幂,然后用快速幂求,再把所有求幂得到的结果乘起来。
http://www.cnblogs.com/sciorz/p/9263122.html
import java.math.*;
import java.util.*;
public class Main {//筛法求素数
    static final int maxn=120050;
    static boolean[]isprime=new boolean[maxn];
    static int[] prime=new int[maxn];
    static int pz=0;
    static void getPrime() {
        for(int i = 2; i < maxn; ++i) isprime[i]=true;
        for(int i = 2; i < maxn; ++i) {
            if(isprime[i]) prime[pz++]=i;
            for(int j = 0; j < pz&&(long)i*prime[j]<maxn; ++j) {
                isprime[i*prime[j]]=false;
                if(i%prime[j]==0) break;
            }
        }
    }
    static Scanner cin=new Scanner(System.in);
    static int n=0;
    public static void main(String[] args) {
        n=cin.nextInt();
        getPrime();
        BigInteger ans=B(1);
        for(int i = 0; i < pz&&prime[i]<=2*n; ++i) {
            int cnt=0,p=prime[i];
            int t=n*2;
            while(t>0) {//(2n!)
                cnt+=t/p;
                t/=p;
            }
            t=n;
            while(t>0) {//(n!*n!)
                cnt-=t/p*2;
                t/=p;
            }
            ans=ans.multiply(pow(p,cnt));
        }
        System.out.println(ans.divide(B(n+1)));
    }
    static BigInteger pow(int x,int n) {//快速积
        BigInteger ans=B(1),base=B(x);
        while(n>0) {
            if(n%2==1) ans=ans.multiply(base);
            base=base.multiply(base);
            n>>=1;
        }
        return ans;
    }
    static BigInteger B(int x) {
        return BigInteger.valueOf(x);
    }
}
View Code