[HDU4372] Count the Buildings
阿新 • • 發佈:2020-09-08
前言
第一類斯特林數,有思維難度
題目
講解
考慮最高的那棟房子會被兩邊計算,除去它,還剩\(n-1\)棟房子
左邊能看見的有\(F-1\)棟房子,右邊能看見\(B-1\)棟房子
我們先考慮左邊一邊
如果我們選出了能被看見的\(F-1\)棟房子,剩下的所有高度小於它們的房子都會在它們的右邊
對於每一棟選出的房子都會形成一條長龍,後面跟的就是高度小於它的房子,但不一定高度小於它的房子剛好跟在它後面
把這個看作一組,發現這一組便是第一類斯特林數中的一個環(重難點)
我們總共需要\(F-1+B-1\)個這樣的環,方案數即為\(s[n-1][F+B-2]\),這裡的\(s\)陣列是第一類斯特林數
然後我們要在\(F+B-2\)個環中選出\(F-1\)個放在左邊,順序為根據排頭高度遞增
所以答案還要乘上\(C_{F+B-2}^{F-1}\)
最終的答案即為\(s[n-1][F+B-2]*C_{F+B-2}^{F-1}\)
記得判無解
程式碼
int C[MAXN][MAXN],s[MAXN][MAXN]; void pre(int x) { s[0][0] = C[0][0] = 1; for(int i = 1;i <= x;++ i) { C[i][0] = 1; for(int j = 1;j <= i;++ j) C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD,s[i][j] = (s[i-1][j-1] + 1ll * (i-1) * s[i-1][j]) % MOD; } } int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); pre(2000); for(int T = Read(); T ;-- T) { n = Read();F = Read();B = Read(); if(F+B-2 > n-1) {Put(0,'\n');continue;} Put(1ll * s[n-1][F+B-2] * C[F+B-2][F-1] % MOD,'\n'); } return 0; }