题解:P1044 [NOIP 2003 普及组] 栈
题解:P1044 [NOIP 2003 普及组] 栈
- Link | Blog
- 直接按照卡特兰数做即可,但是考虑证明。
前置知识
- 卡特兰数:组合数学中一种常出现于各种计数问题中的数列。它的前几项为:
C(0)=1,C(1)=1,C(2)=2,C(3)=5,C(4)=14,C(5)=42 题目思路
- 不妨设第一个入栈的元素是第
k 个出栈的元素,则前面的元素1 \sim k-1 必须在k 前完成出入栈。则方案数为C(k-1) ; - 则后面的数
k \sim n 有C(n-k) 种方案。总的方案数为C(k-1) \cdot C(n-k) 。 - 可以把样例代入证明:
- 当
k=1 时,有C(0) \cdot C(2)=2 ; - 当
k=2 时,有C(1) \cdot C(1)=1 ; - 当
k=3 时,有C(2) \cdot C(0)=2 ; - 因此总方案为
2+1+2=5 。
- 当
- 综上,答案为:
C(n)=\sum _{k=1}^{n} C(k−1) \cdot C(n−k) - 将其化为:
C(n)=\frac{2(2n−1)}{n+1} \cdot C(n−1) 于是我们可以推出卡特兰数列的前
18 项,然后根据n 输出即可。代码实现
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100;
ll n,sum[N];
int main() {
cin>>n;
sum[1]=1;
for(int i=2;i<=18;i++){
sum[i]=sum[i-1]*2*(2*i-1)/(i+1);
//cout<<sum[i]<<"\n";
}
cout<<sum[n];
return 0;
}