# 斯特林数（Stirling Number）与放球问题，以及 HDU 4372 Count the Buildings 题解……

/ 0评 / 0
• 你有 n 个不同的小球，现在你想用这些小球拼成 k 个环，一共有多少种拼法？
• 你有 n 个不同的小球，现在你想将这些小球分成 k 个非空的集合，一共有多少种分法？

## 第一类斯特林数

\displaystyle s(i,j)=s(i-1,j-1)+(i-1)\ast s(i-1,j)

## 第二类斯特林数

\displaystyle S(i,j)=S(i-1,j-1)+j\ast S(i-1,j)

S(i,j) 的其他表示方法是 S_i^{(j)} 或者 \begin{Bmatrix} i \\\\ j \end{Bmatrix}

## 例题：HDU 4372：Count the Buildings

### Problem Description

There are N buildings standing in a straight line in the City, numbered from 1 to N. The heights of all the buildings are distinct and between 1 and N. You can see F buildings when you standing in front of the first building and looking forward, and B buildings when you are behind the last building and looking backward. A building can be seen if the building is higher than any building between you and it.
Now, given N, F, B, your task is to figure out how many ways all the buildings can be.

### Input

First line of the input is a single integer T (T<=100000), indicating there are T test cases followed.
Next T lines, each line consists of three integer N, F, B, (0<N, F, B<=2000) described above.

### Output

For each case, you should output the number of ways mod 1000000007(1e9+7).

### Sample Input

2
3 2 2
3 2 1


### Sample Output

2
1


### Solution

\displaystyle s(n-1,a-1+b-1)\ast C_{a-1+b-1}^{a-1}

### Code

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=2005,tt=1e9+7;
int T,n,a,b,f[maxn][maxn],c[maxn][maxn];
int ret=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
inline void MakeDP(){
f[1][1]=1;
for (int i=2;i<=2000;i++)
for (int j=1;j<=i;j++)
f[i][j]=((long long)f[i-1][j-1]+(long long)(i-1)*f[i-1][j]%tt)%tt;
for (int i=0;i<=2000;i++) c[i][0]=1;
for (int i=1;i<=2000;i++){
c[i][0]=c[i][i]=1;
for (int j=1;j<i;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%tt;
}
}
int main(){
MakeDP();
while (T--){
if (a+b-2>2000){printf("0\n");continue;}
printf("%lld\n",(long long)f[n-1][a-1+b-1]*c[a-1+b-1][a-1]%tt);
}
return 0;
}