题目描述
有n个高度分别为1到n的人,从前到后站成一列,站在前面的人会挡住后面比他矮的人。现从前面一共能看见m个人,请问有多少种可能的站法
输入格式
第一行两个整数n,m含义如图所述
输出格式
一行一个整数,为答案模1e9+7的值
数据范围
时间限制1s,空间限制:512M
样例1
Input
3 2
Output
3
样例1解释
一共有132、231、213三种排法使得从前面能看见恰好两个人
样例2
Input
1000 500
Output
761367694
先打个表看一下
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3+2;
const int inf = 0x3f3f3f3f;
ll n, m;
int a[maxn], dp[maxn], q[maxn];
int main() {
//cin>> n >> m;
for (int n = 1; n <= 10; n++){
for (int m = 1; m <= n; m++){
for (int i = 0; i < n;i++) a[i] = i + 1;
int ans = 0;
do{
int las = 0;
for (int i = 0; i < n; i++){
if (a[i] > las) dp[i] = dp[i - 1] + 1, las = a[i];
else dp[i] = dp[i - 1];
}
if (dp[n - 1] == m) ans++;
}while (next_permutation(a, a+n));
printf("%d\t", ans);
}
printf("\n");
}
return 0;
}
发现是第一类斯特林数
可以理解为n个元素,分成m组,每组把最大的站最前面,然后把这m组按站的最前面的身高由小到大排列,符合第一类斯特林数的使用条件
#include<bits/stdc++.h>
using namespace std;
#define RI register int
typedef long long ll;
const int N=1005;
const long long M = 1e9 + 7;
int n,A,B,ans,a[18][N],rev[N],m,G;
long long mod;
const int maxn = 1005;
ll Stirling[maxn][maxn], fac[maxn] = {1};
void init() {
for(ll i = 1; i < maxn; i++)
fac[i] = fac[i - 1] * i % M;
Stirling[0][0] = 0;
Stirling[1][1] = 1;
for(ll i = 2; i < maxn; i++) {
for(ll j = 1; j <= i; j++) {
Stirling[i][j] = (Stirling[i - 1][j - 1] % M + (i - 1) * Stirling[i - 1][j] % M +M) % M;
}
}
}
signed main(){
scanf("%lld%lld", &n, &m);
init();
cout << Stirling[n][m] % M << endl;
}