HDU4372 Count the Buildings (+题解:斯特林数)
题面
(笔者翻译)
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.
有n座高楼,从左往右数第 i 座楼的高度为 ai,每座高楼高度互不相同,且 1 ≤ ai ≤ n ,换言之,n座高楼高度形成的序列为1~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.
如果有平行光从最左端往右照,那么光能照到的高楼数为 F,如果有平行光从最右端往左照,那么光能照到的高楼数为 B,


(上图为F = 3,B = 2的一个例子)
Now, given N, F, B, your task is to figure out how many ways all the buildings can be.
告诉你n,F和B,让你求符合n、F 、B条件的合法序列有多少个
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).
有最多1e5个数据,n、F、B都是小于等于2000的正整数,最终答案要取模 1e9+7。
题解
既然每个高度不相同,那么对F和B有重复贡献的有且仅有最高的那座楼,
最高的楼左边有F-1个递增排列的楼,每座楼到右边那座比它高的楼中间都有一堆小弟(比它小),
最高的楼右边有B-1个递减排列的楼,每座楼到左边那座比它高的楼中间也有一堆小弟(比它小),
那么说,除了最高的楼之外,其他的楼共有F+B-2个团体,每个团体有一座最高的楼(要算贡献的楼)和一堆小弟(可以没有),
从中选F-1个团体到最大楼的左边(组合数C(F+B-2 , F-1)),他们之间的顺序就确定了(递增),然后小弟们就在对应老大右边乱排列,
剩下的B-1个团体到最大楼的右边(加起来正好 F+B-2 个),他们之间的顺序也确定了(递减),然后小弟们就在对应老大左边乱排列,
想好了放团体的方案数后,我们来想安排团体内部的方案
对于每个团体,把最大的一个拉入队首,剩下的随便排,
这不就是圆排列吗?相关于把每个圈最大的一个转到第一个。
所以,分团体以及安排团体内部的顺序的方案数就是 s(n-1,F+B-2) (第一类斯特林数)
把s(n-1,F+B-2)和C(F+B-2 , F-1)乘起来完事,
注意T很大,因此要n^2预处理s和C,然后判断无解的情况。
CODE
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<algorithm>
#define MAXN 2005
#define MAXM 35
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x)&(x))
//#define int LL
using namespace std;
inline LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s == '-')f = -1;s = getchar();}
while(s >= '0' && s <= '9') {x = x * 10 + (s - '0');s = getchar();}
return x * f;
}
const int jzm = 1000000007;
int n,m,i,j,o,k;
int s[MAXN][MAXN],C[MAXN][MAXN];
int main() {
s[0][0] = 1;
C[0][0] = 1;
for(int i = 1;i <= 2000;i ++) {
C[i][0] = 1;
for(int j = 1;j <= i;j ++) {
s[i][j] = (s[i-1][j-1] +0ll+ (i-1ll) *1ll* s[i-1][j] % jzm) % jzm;
C[i][j] = (C[i-1][j-1] +0ll+ C[i-1][j]) % jzm;
}
}
int T = read();
while(T --) {
n = read();
int F = read(),B = read();
if(F+B-1 > n || max(F,B) <= 1) {
printf("0\n");
continue;
}
int ans = s[n-1][F+B-2] *1ll* C[F+B-2][F-1] % jzm;
printf("%d\n",ans);
}
return 0;
}
第一类斯特林数
简单解释一下

想增进了解的点这里
HDU4372 Count the Buildings (+题解:斯特林数)的更多相关文章
- 【HDU 4372】 Count the Buildings (第一类斯特林数)
Count the Buildings Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- HDU 4372 Count the Buildings——第一类斯特林数
题目大意:n幢楼,从左边能看见f幢楼,右边能看见b幢楼 楼高是1~n的排列. 问楼的可能情况 把握看到楼的本质! 最高的一定能看见! 计数问题要向组合数学或者dp靠拢.但是这个题询问又很多,难以dp ...
- HDU 4372 Count the Buildings [第一类斯特林数]
有n(<=2000)栋楼排成一排,高度恰好是1至n且两两不同.现在从左侧看能看到f栋,从右边看能看到b栋,问有多少种可能方案. T组数据, (T<=100000) 自己只想出了用DP搞 发 ...
- hdu 4372 Count the Buildings 轮换斯特林数
题目大意 n栋楼有n个不同的高度 现在限制从前面看有F个点,后面看有B个点 分析 最高那栋楼哪都可以看到 剩下的可以最高那栋楼前面分出F-1个组 后面分出B-1个组 每个组的权值定义为组内最高楼的高度 ...
- HDU4372 Count the Buildings —— 组合数 + 第一类斯特林数
题目链接:https://vjudge.net/problem/HDU-4372 Count the Buildings Time Limit: 2000/1000 MS (Java/Others) ...
- [Hdu4372] Count the Buildings
[Hdu4372] Count the Buildings Description There are N buildings standing in a straight line in the C ...
- 【HDU4372】Count the Buildings (第一类斯特林数)
Description $N$座高楼,高度均不同且为$1~N$中的数,从前向后看能看到$F$个,从后向前看能看到$B$个,问有多少种可能的排列数. $T$组询问,答案模$1000000007$.其中$ ...
- hdu 4372 Count the Buildings —— 思路+第一类斯特林数
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4372 首先,最高的会被看见: 然后考虑剩下 \( x+y-2 \) 个被看见的,每个带了一群被它挡住的楼, ...
- 【题解】CJOI2019 登峰造鸡境 (Prufer序列+斯特林数)
[题解]CJOI2019 登峰造鸡境 (Prufer序列+斯特林数) 题目背景 舒服了. 题目描述 你有一颗n个点的无根树,每个点有有一个标号(1~n). 现在你知道,总共有m个叶子节点,求不同的树的 ...
随机推荐
- ACL权限控制
ALC讲述比较详细 https://zhuanlan.zhihu.com/p/360158311
- Python if-else的简单表示
常见写法 a = 1 b = 1 c = 2 if a == b: print("true") elif a == c: print("false") else ...
- LVS+keepalived简单搭建(二)
在LVS1的基础上进行搭建 https://www.cnblogs.com/hikoukay/p/12860476.html keeplived主机 用node01,node04两台 先清掉原先nod ...
- 【Java面试】@Resource 和 @Autowired 的区别
Hi,大家好,我是Mic. 一个工作2年的粉丝,问我一个Spring里面的问题. 希望我能从不同的视角去分析,然后碾压面试官. 这个问题是: "@Resource和@Autowired&qu ...
- 如何在vscode 背景配置一个动态小女孩
D:\Microsoft VS Code\resources\app\out\vs\code\electron-browser\workbench <!-- Copyright (C) Micr ...
- (win环境)使用Electron打造一个桌面应用翻译小工具
初始化项目 npm init 修改package.json {"name": "trans","version": "1.0.0& ...
- 我熬夜开发了一款简约实用、支持多平台的Markdown在线编辑器(开源)
前言 之前,一直想开发一款属于自己的Markdown编辑器,主要是自己平常写文章可以更加灵活操作,另外扩宽自己的视野也是非常不错的选择啊!所以在周末就决定玩耍一番.首先我调研了很多线上热门的md编辑器 ...
- BluePrism手把手教程2.0 创建流程
2.0.1 创建流程 2.0.2 设置流程名称 2.0.3 添加流程说明 2.0.4 添加流程成功 2.0.4 打开新建的流程 RPA行业微信交流群,欢迎大家扫码加入一起交流,此群用于RPA行业技术. ...
- 你真的会python中的for循环吗
for 循环是 Python 中的通用序列迭代器:它可以单步遍历任何有序序列中的元素.for 语句适用于字符串.列表.元组.其他内置可迭代对象和类创建的新对象. for 通常比 while 循环更容易 ...
- 【docker专栏3】docker基础概念-容器、镜像以及引擎组成部分
一.docker镜像与容器 docker镜像是一个可执行的静态独立软件包,包含打包程序代码和软件运行环境等文件.如:代码.运行时库.环境变量和配置文件等都包含在其中.容器是镜像的运行时状态(镜像中的软 ...