棧 卡特蘭數 火車進出棧問題

2021-10-02 12:06:50 字數 1851 閱讀 6951

傳送門

題意:一列火車n節車廂,依次編號為1,2,3,…,n。

每節車廂有兩種運動方式,進棧與出棧,問n節車廂出棧的可能排列方式有多少種。

資料範圍

1≤n≤60000

輸入樣例:

3輸出樣例:

5思路:進出棧問題–>序列問題–>路徑問題。

這顯然是上一道火車進棧的公升級版,資料太大不能再進行遞迴處理了。問題轉換:尋找滿足條件的 『+』,』-『序列,即把進棧用』+『標記,出棧用』-『標記;滿足字首和中』-『的數量小於等於』+『的數量就是合法的。例如:231轉換成序列便是+ + - + - -。

就相當於在2n個位置找n個位置放+的方案數減去不合法的方案數。

而這個不合法數怎麼求呢?這就很神奇了,我們可以把它轉化成路徑問題:在乙個座標走上,從(0,0)走到(n,n)的位置,往右表示』+』,往上表示』-』;那麼所有在y=x以下的路徑都是合法路徑(滿足x>=y,即字首和的』+』 > 『-』);而所有與y=x+1有交點的路徑都是不合法的路徑,那麼我們找到每條不合法路徑與y=x+1的第乙個交點,將交點以後的部分關於y=x+1對稱後終點都會是(n-1,n+1),如此每一天不合法路徑都和其改變後的路徑相對應,由此所有從(0,0)走到(n-1,n+1)的路徑就是不合法的路徑。

顯然的用高精度來解決這個問題,但是如果我們先算乘法再來做除法的話就會超時,這樣我們可以想辦法只用乘法:找出分子分母共有的質因子數,將它們相互抵消(如分子含義2 ^ x,分母含義2 ^ y,那麼我們就可以相互抵消掉後分母乘以2^(y-x));如此找到所有的質因子數並進行抵消最後得到答案。

**實現:

#include

#include

#include

using

namespace std;

typedef

long

long ll;

const

int n =

6000010

, m =

120010

;ll res[n]

, tt;

int q[m]

;bool s[m]

;//高精度乘法

void

multi

(int b)

while

(t)}

//壓位輸出,可以提高速度

void

out(

)//返回n!裡面有多少個因子p,即n!裡面p的次數是多少

intget

(int n,

int p)

return s;

}int

main()

int k = n +1;

for(

int i =

2; i <= k; i ++

)while

(k % i ==0)

res[0]

=1;for

(int i =

2; i <= n *

2; i ++

)while

(q[i]--)

multi

(i);

out();

return0;

}

火車進出棧問題 卡特蘭數

更新提示 第一次更新 正文 一列火車n節車廂,依次編號為1,2,3,n。每節車廂有兩種運動方式,進棧與出棧,問n節車廂出棧的可能排列方式有多少種。乙個數,n n 65000 乙個數s表示n節車廂出棧的可能排列方式 35轉換一下題意 求卡特蘭數的第 n 項,不取模。先考慮 n 小一點的做法,我們可以直...

火車進出站問題 棧

編號為1,2,n的n輛火車依次進站,給定乙個n的排 列,判斷是否是合法的出站順序?思路 先把出站順序存入,用棧模擬進站的火車,按照出站的順序,依次pop出來,判斷 最後的出站數量能否達到n。include include include using namespace std const int m...

棧和卡特蘭數(Catalan number)

棧是計算機中經典的資料結構,我們也會遇到乙個常見的問題 一共有多少種合法的出棧順序?先說一下什麼是合法的出棧序列,凡是合法序列都遵循以下規律 即對於出棧序列中的每乙個數字,在它後面的 比它小的所有數字,一定是按遞減順序排列的。例如 有數字1 2 3 4 依次入棧,那麼他們的出棧順序中 所以到底有多少...