1. 程式人生 > >HDOJ 4372 第一類斯特林數

HDOJ 4372 第一類斯特林數

我們 一個 log edi upload 個數 題解 pid spa

鏈接:

http://acm.split.hdu.edu.cn/showproblem.php?pid=4372

題意:

有一系列的樓房,高度從1~n,然後從左側看能看到f個樓房,右側看能看到b個樓房,問有多少個方案數滿足。

題解:

首先我們知道一個結論:n的環排列的個數與n-1個元素的排列的個數相等,因為P(n,n)/n=(n-1)!。

可以肯定,無論從最左邊還是從最右邊看,最高的那個樓一定是可以看到的.

假設最高的樓的位置固定,最高樓的編號為n,那麽我們為了滿足條件,可以在樓n的左邊分x-1組,右邊分y-1組,

且用每組最高的那個元素代表這一組,那麽樓n的左邊,從左到右,組與組之間最高的元素一定是單調遞增的,

且每組中的最高元素一定排在該組的最左邊,每組中的其它元素可以任意排列(相當於這個組中所有元素的環排列)。右邊反之亦然。

然後,可以這樣考慮這個問題,最高的那個樓左邊一定有x-1個組,右邊一定有y-1個組,且每組是一個環排列,

這就引出了第一類Stirling數(技術分享個人分成技術分享組,每組內再按特定順序圍圈的分組方法的數目)。

我們可以先把n-1個元素分成x-1+y-1組,然後每組內部做環排列。再在所有組中選取x-1組放到樓n的左邊。所以答案是

ans(n, f, b) = C[f + b - 2][f - 1] * S[n - 1][f + b - 2];

代碼:

31 ll stir[MAXN][MAXN];
32 ll C[MAXN][MAXN]; 33 34 void init() { 35 stir[1][0] = 0; 36 stir[1][1] = 1; 37 rep(i, 2, MAXN) rep(j, 1, i + 1) 38 stir[i][j] = (stir[i - 1][j - 1] + (i - 1)*stir[i - 1][j]) % MOD; 39 rep(i, 1, MAXN) { 40 C[i][0] = C[i][i] = 1; 41 rep(j, 1, i) C[i][j] = (C[i - 1
][j] + C[i - 1][j - 1]) % MOD; 42 } 43 } 44 45 int main() { 46 ios::sync_with_stdio(false), cin.tie(0); 47 init(); 48 int T; 49 cin >> T; 50 while (T--) { 51 int n, f, b; 52 cin >> n >> f >> b; 53 cout << C[f + b - 2][f - 1] * stir[n - 1][f + b - 2] % MOD << endl; 54 } 55 return 0; 56 }

HDOJ 4372 第一類斯特林數