题目
一列火车n节车厢,依次编号为1,2,3,…,n。
每节车厢有两种运动方式,进栈与出栈,问n节车厢出栈的可能排列方式有多少种。
输入格式
输入一个整数n,代表火车的车厢数。
输出格式
输出一个整数s表示n节车厢出栈的可能排列方式数量。
数据范围
1≤n≤60000
输入样例:
3
输出样例:
5
分析
- 这个题目就是求卡特兰数,卡特兰数是一种用途非常广的递推数列。
- 下面给出用组合数求卡特兰数的代码。
代码
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const int N=120005;
const ll mod=100000000;
int primes[N],cnt,opt[N];
bool str[N];
void primesai(int r){//素数筛
for(int i=2;i<=r;i++){
if(!str[i]){
primes[cnt++]=i;
for(int j=i;j<=r;j+=i){
str[j]=true;
}
}
}
}
int get(int n,int p){//获得n!中含有多少个p^1,p^2...这种质数
int s=0;
while(n){
s+=n/p;
n/=p;
}
return s;
}
void muilt(vector<ll> &res,ll b){// 压位高精度乘法
ll t=0;
for(int i=0;i<res.size();i++){
res[i]=res[i]*b+t;
t=res[i]/mod;
res[i]%=mod;
}
while(t){
res.push_back(t%mod);
t/=mod;
}
}
void out(vector<ll> res){ // 输出高精度整数
printf("%lld",res.back());
for(int i=res.size()-2;i>=0;i--){
printf("%09lld",res[i]);
}
}
int main()
{
int n;
cin>>n;
primesai(n*2);
for(int i=0;i<cnt;i++){ //质因数分解 求质因数个数
int p=primes[i];
opt[p] = get(n*2,p)-get(n,p)-get(n+1,p);
}
vector<ll> res;
res.push_back(1);
for(ll i=2;i<=2*n;i++){
for(ll j=0;j<opt[i];j++){
muilt(res,i);
}
}
out(res);
return 0;
}