傳送門
題意:一列火車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 依次入棧,那麼他們的出棧順序中 所以到底有多少...