卡特兰数
定义:长度为n,且由0和1组成的字符串,满足任意前缀中0的个数不小于1的个数的方法数。
公式:
经典问题
火车进出站的方案数(这道题由于数据范围过大,用了质因子分解的方法,本质是卡特兰数)
// 卡特兰数:C(2n, n) / (n + 1)#include<cstdio>#include<cstring>using namespace std;typedef long long int64;const int N = 6000000, M = 1e9;int64 a[N];int tt = 0;bool st[60010 * 2];int p[60010 * 2];void out() {for(int i = tt - 1; i >= 0; i--) {if(i == tt - 1) {printf("%lld", a[i]);}else {printf("%09lld", a[i]);}}printf("\n");}void multi(int prime) {int64 t = 0;for(int i = 0; i < tt; i++) {t += a[i] * prime;a[i] = t % M;t /= M;}while(t) {a[tt++] = t % M;t /= M;}}int get(int64 num, int prime) {int ans = 0;while(num) {ans += num / prime;num /= prime;}return ans;}int main() {memset(st, 0, sizeof st);memset(p, 0, sizeof p);memset(a, 0, sizeof a);int n;scanf("%d", &n);for(int i = 2; i <= 2 * n; i ++) {if(st[i]) {continue;}for(int j = i * 2; j <= 2 * n; j += i) {st[j] = true;}}for(int i = 2; i <= 2 * n; i++) {if(!st[i]) {p[i] = get(2 * n, i) - get(n, i) * 2;}}int k = n + 1;for(int i = 2; i <= k; i++) {if(!st[i]) {while(k % i == 0) {k /= i;p[i]--;}}}a[tt++] = 1;for(int i = 2; i <= 2 * n; i++) {//if(p[i]) printf("p[%d]: %d\n", i, p[i]);while(p[i]) {multi(i);p[i]--;}}out();return 0;}
