您的位置:首页 > 产品设计 > UI/UE

[HDU]4372 Count the Buildings 第一类斯特林数

2018-01-19 21:47 465 查看


Count the Buildings

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 2460    Accepted Submission(s): 804


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

 

Source

2012 Multi-University Training Contest 8

  专爆RE差评...

  这道题大意就是说一个n高度不同的房屋, 从左边看能看到f个, 从右边看能看到b个. 问方案数.

  实际上就是楼房就是排列... 那么从左往右和从右往左显然最后能看到的就是那个最高的房屋. 于是我们考虑那个最高的. 那么最高的左边有f - 1个可见房屋, 右边有b - 1个可见房屋. 那么我们把一个可见房屋到下一个可见房屋之前分为一段. 则最高的房屋左边就有f - 1段, 右边有b - 1段. 我们先考虑左边的f - 1段. 对于左边每一段, 因为由我们分段的方式, 这一段最高的房屋一定在这一段的左端——那么也就是说本段其他的元素可以随便排列. 那么实际上我们会发现每段就是一个圆排列. 右边的跟左边同样的分析方法.
那么我们现在相当于在除了最高的房屋, 剩下的n - 1个不同元素(房屋) 选出(f - 1) + (b - 1)个圆排列(段)来, 并选择f - 1个放在左边, 剩下的放在右边. 显然把f - 1个放在左边不用再讨论这f - 1段(圆排列)的先后次序, 因为题目中要求高度递增(从左到右), 那么选择了f - 1段后放在左边的方式就固定了. 右边同理. 那么对于n - 1个元素里选出f + b- 2个圆排列来——这显然就是第一类斯特林数的定义. 而后面的选择直接上组合数就可以了.

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2005;
const int mod = 1e9 + 7;
int T, n, x, y;
long long c[maxn][maxn], s[maxn][maxn];
void init() {
for (int i = 0; i < maxn; ++ i) {
c[i][0] = 1;
s[i][0] = (!i) ? 1 : 0;
for (int j = 1; j <= i; ++ j) {
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
s[i][j] = (s[i - 1][j - 1] + (i - 1) * s[i - 1][j] % mod) % mod;
}
}
}
int main() {
init();
scanf("%d", &T);
while (T --) {
scanf("%d%d%d", &n, &x, &y);
if (x + y - 2 > 2000) puts("0");
else printf("%lld\n", s[n - 1][x + y - 2] * c[x + y - 2][x - 1] % mod);
}
}

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: