洛谷P1044 :棧(卡特蘭數)
https://www.luogu.org/problemnew/show/P1044
題目背景
棧是計算機中經典的資料結構,簡單的說,棧就是限制在一端進行插入刪除操作的線性表。
棧有兩種最重要的操作,即pop(從棧頂彈出一個元素)和push(將一個元素進棧)。
棧的重要性不言自明,任何一門資料結構的課程都會介紹棧。寧寧同學在複習棧的基本概念時,想到了一個書上沒有講過的問題,而他自己無法給出答案,所以需要你的幫忙。
題目描述
寧寧考慮的是這樣一個問題:一個運算元序列,1,2,.....n(圖示為1到3的情況),棧A的深度大於n。
現在可以進行兩種操作,
-
將一個數,從運算元序列的頭端移到棧的頭端(對應資料結構棧的push操作)
-
將一個數,從棧的頭端移到輸出序列的尾端(對應資料結構棧的pop操作)
使用這兩種操作,由一個運算元序列就可以得到一系列的輸出序列,下圖所示為由123生成序列231的過程。
(原始狀態如上圖所示)
你的程式將對給定的n,計算並輸出由運算元序列1,2,…,n經過操作可能得到的輸出序列的總數。
輸入輸出格式
輸入格式:
輸入檔案只含一個整數n(1≤n≤18)
輸出格式:
輸出檔案只有1行,即可能輸出序列的總數目
設 x 為當前出棧序列的最後一個,則x有n種取值,因為每一個數都可能最後出棧。
由於x是最後一個出棧的,所以可以將已經出棧的數分成兩部分
-
比x小
-
比x大
比x小的數有x-1個,所以這些數的全部出棧可能為f[x-1]
比x大的數有n-x個,所以這些數的全部出棧可能為f[n-x]
所以一個x的取值能夠得到的所有可能性為f[x-1] * f[n-x]
另外,由於x有n個取值,所以
ans = f[0]*f[n-1] + f[1]*f[n-2] + ... + f[n-1]*f[0];
這就是所謂的卡特蘭數。
#include<stdio.h> #define N 20 long long a[N]; int main() { int n,i,j; scanf("%d",&n); a[0]=1; a[1]=1; for(i=2;i<=n;i++) { for(j=0;j<i;j++) a[i]+=a[j]*a[i-j-1]; } printf("%lld\n",a[n]); return 0; }
題目描述
小和尚每日練武真的是很累啊,但是為了以後更和諧。也沒有辦法了,只能天天那刻苦了;有一日練武結束後去找師傅聊天,猛然間,師傅說到,其實在這個世界上想混的好的話,光武功高是不行的,也要能噴能聊,你們要多讀書了,從此以後小和尚每天都要抽出一部分時間來讀書,有一天看到了一個叫卡特蘭數的東西,看了半天你沒有看懂,只知道是個數列,因此想讓小朋友們幫忙找到數列前邊的一些卡特蘭數;快快幫忙吧;
注: 卡特蘭數遞推關係的解為:
h(n)=C(2n,n)/(n + 1) (n=1,2,3,)
輸入
輸入資料有多組,每組資料首先輸入一個整數n(n<=30). 然後有n個正整數m(每個正整數m<50);
輸出
對於每個正整數m,輸出相應的卡特蘭數,每個數佔一行;
樣例輸入
3 1 2 3
樣例輸出
1 2 5
#include<stdio.h>
#define N 35
long long a[N];
int main()
{
int n,i,j,t;
a[0]=1;
a[1]=1;
for(i=2;i<=30;i++)
{
for(j=0;j<i;j++)
a[i]+=a[j]*a[i-j-1];
}
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
printf("%lld\n",a[n]);
}
return 0;
}