【出栈序列个数】 火车进出站问题

传送门

题意

\(1\sim n\)的序列依次进栈,出栈的排列有多少种

数据范围

\(1\leq n\leq 6\times 10^{4}\)

题解

Catalan数,求组合数即可

Code

#include <bits/stdc++.h>
using namespace std;
#define ll long long 
const int N=120010;

ll primes[N],cnt,sum[N];
ll ans[N], tt, n;
bool st[N];

void get_primes(ll n){
    for (int i = 2; i <=n ; ++i) {
        if(!st[i]) primes[cnt++] = i;
        for (int j = 0; primes[j] <= n / i ; ++j) {
            st[primes[j] * i] = true;
            if(i % primes[j] == 0) break;
        }
    }
}
int get(ll n, ll p) {
    int res = 0;
    while(n){
        res += n / p;
        n /= p;
    }
    return res;
}
void multi(int b) {
    ll t = 0;
    for (int i = 0; i <= tt; i ++ ) {
        ans[i] = ans[i] * b + t;
        t = ans[i] / 1000000000;
        ans[i] %= 1000000000;
    }
    while (t) {
        ans[++tt] = t % 1000000000;
        t /= 1000000000;
    }
}
void out() {
    printf("%lld", ans[tt]);
    for (int i = tt - 1; i >= 0; i -- ) 
        printf("%09lld", ans[i]);
    cout << endl;
}
int main(){
    scanf("%lld", &n);
    get_primes(2 * n);

    for (int i = 0; i < cnt ; ++i) {
        ll p = primes[i];
        sum[i] = get(2 * n, p) - get(n, p) - get(n + 1, p);
    }
    ans[0] = 1;
    for (int i = 0; i < cnt; ++i)
        for (int j = 1; j <= sum[i]; ++j)
            multi(primes[i]);
    out();
}
posted @ 2020-07-11 11:48  Hyx'  阅读(216)  评论(0编辑  收藏  举报