P4609 建筑师
题目描述
小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 n 个建筑,每个建筑的高度是 1 到 n 之间的一个整数。
小 Z 有很严重的强迫症,他不喜欢有两个建筑的高度相同。另外小 Z 觉得如果从最左边(所有建筑都在右边)看能看到 A 个建筑,从最右边(所有建筑都在左边)看能看到 B 个建筑,这样的建筑群有着独特的美感。现在,小 Z 想知道满足上述所有条件的建筑方案有多少种?
如果建筑 i 的左(右)边没有任何建造比它高,则建筑 i 可以从左(右)边看到。两种方案不同,当且仅当存在某个建筑在两种方案下的高度不同。
输入格式
第一行一个整数 T,代表 T 组数据。 接下来 T 行,每行三个整数 n,A,B。
输出格式
对于每组数据输出一行答案 mod 1e9+7。
输入输出样例
输入 #1
2
3 2 2
3 1 2
输出 #1
2
1
说明/提示
对于 100% 的数据 :1≤n≤50000, 1≤A,B≤100, 1≤T≤2000001。
这也出到我考试题里了,看到后一脸懵,题都没看懂(因为是简化题面),爆0了(我吐了)
这道题正解是组合数\(+\)第一类斯特林数。
我们如果要有A个前缀最大值,B个后缀最大值,我们可以把\(n\)个数分为\(A + B - 1\)段:高度为\(n\)的为一段,其余的是一个高的挡住一群矮的为一段,大概是这样的:
那么问题可以转化为:将\(n - 1\)个数分为\(A + B - 2\)段,并且每一段不能为空,这不就是第一类斯特林数吗?
最后再考虑每一段在最高的那段左边还是右边就好了,最高的那段左边应该有\(A - 1\)段,右边应该有\(B - 1\)段,所以再乘上个\(C_{A +B - 2} ^ {A - 1}\)就好了。
#include <iostream>
#include <cstdio>
#include <cctype>
using namespace std;
inline long long read() {
long long s = 0, f = 1; char ch;
while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
return s * f;
}
const int N = 3005, M = 3005, mod = 998244353;
int n, a, b;
int jc[N], inv[N], c[M][M], s[N][M];
void make_C() {
jc[0] = jc[1] = inv[0] = inv[1] = 1;
for(int i = 2;i <= M - 5; i++) jc[i] = 1ll * jc[i - 1] * i % mod;
for(int i = 2;i <= M - 5; i++) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
for(int i = 2;i <= M - 5; i++) inv[i] = 1ll * inv[i - 1] * inv[i] % mod;
for(int i = 0;i <= M - 5; i++) c[i][0] = 1;
for(int i = 1;i <= M - 5; i++) {
for(int j = 1;j <= M - 5; j++) {
if(i >= j) c[i][j] = 1ll * jc[i] * inv[j] % mod * inv[i - j] % mod;
}
}
s[0][0] = s[1][1] = 1;
for(int i = 2;i <= N - 5; i++) s[i][1] = 1ll * s[i - 1][1] * (i - 1) % mod;
for(int i = 2;i <= N - 5; i++) {
for(int j = 2;j <= M - 5; j++) {
if(i >= j) s[i][j] = (s[i - 1][j - 1] + 1ll * s[i - 1][j] * (i - 1) % mod) % mod;
}
}
}
void init() {
scanf("%d %d %d", &n, &a, &b);
}
void work() {
printf("%lld\n", 1ll * s[n - 1][a + b - 2] * c[a + b - 2][a - 1] % mod);
}
int main() {
// freopen("onesentence.in","r",stdin); freopen("onesentence.out","w",stdout);
make_C();
init(); work();
// fclose(stdin); fclose(stdout);
return 0;
}
P4609 建筑师的更多相关文章
- Luogu P4609 [FJOI2016]建筑师&&CF 960G Bandit Blues
考虑转化题意,我们发现其实就是找一个长度为\(n\)的全排列,使得这个排列有\(A\)个前缀最大值,\(B\)个后缀最大值,求方案数 我们考虑把最大值拎出来单独考虑,同时定义一些数的顺序排列为单调块( ...
- 洛谷 P4609: [FJOI2016] 建筑师
本省省选题是需要做的. 题目传送门:洛谷P4609. 题意简述: 求有多少个 \(1\) 到 \(N\) 的排列,满足比之前的所有数都大的数正好有 \(A\) 个,比之后的所有数都大的数正好有 \(B ...
- 洛谷P4609 [FJOI2016]建筑师 【第一类斯特林数】
题目链接 洛谷P4609 题解 感性理解一下: 一神带\(n\)坑 所以我们只需将除了\(n\)外的\(n - 1\)个元素分成\(A + B - 2\)个集合,每个集合选出最大的在一端,剩余进行排列 ...
- [洛谷P4609] [FJOI2016]建筑师
洛谷题目链接:[FJOI2016]建筑师 题目描述 小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 \(n\) 个建筑,每个建筑的高度是 \(1\) 到 \(n\) 之间的一 ...
- P4609 [FJOI2016]建筑师
思路 裸的第一类斯特林数,思路和CF960G相同 预处理组合数和第一类斯特林数回答即可 代码 #include <cstdio> #include <cstring> #inc ...
- 洛谷P4609 [FJOI2016]建筑师(第一类斯特林数+组合数)
题面 洛谷 题解 (图片来源于网络,侵删) 以最高的柱子\(n\)为分界线,我们将左边的一个柱子和它右边的省略号看作一个圆排列,右边的一个柱子和它左边的省略号看作一个圆排列,于是,除了中间的最高的柱子 ...
- P4609 [FJOI2016]建筑师(第一类斯特林数)
传送门 没想到连黑题都会有双倍经验的 其实这题本质上是和CF960G Bandit Blues一样的,不过那里是要用分治FFT预处理第一类斯特林数,这里直接打表预处理第一类斯特林数就可以了 //min ...
- LUOGU P4609 [FJOI2016]建筑师(第一类斯特林数)
传送门 解题思路 好神仙的思路,首先一种排列中按照最高点将左右分开,那么就是要在左边选出\(a-1\)个,右边选出\(b-1\)一个,这个如何计算呢?考虑第一类斯特林数,第一类斯特林数是将\(n\)个 ...
- [FJOI2016]建筑师
题目描述 小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 n 个建筑,每个建筑的高度是 1 到 n 之间的一个整数. 小 Z 有很严重的强迫症,他不喜欢有两个建筑的高度相同. ...
随机推荐
- 精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换
本文是精讲RestTemplate第2篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 RestTemplate只是对其他的HTTP客 ...
- FAT32文件系统下的文件、目录管理
背景 FAT32作为一个文件系统,有着广泛的应用.在安装操作系统时,许多个人用户默认都选择FAT32文件系统,因此,了解FAT32文件系统下的文件.目录的管理方式就显得非常必要了. FAT32文件系统 ...
- Linux进程间通信之《共享内存》入门
目录 简述 代码 写端代码 读取端代码 编译 运行 简述 共享内存是Linux系统进程间通信常用的方式,通常用于数据量较大的情况,如果只是用于不同的进程间消息通知,那不如用消息队列或者socket.之 ...
- Focal Loss 损失函数简述
Focal Loss 摘要 Focal Loss目标是解决样本类别不平衡以及样本分类难度不平衡等问题,如目标检测中大量简单的background,很少量较难的foreground样本.Focal Lo ...
- 插槽slot使用方法
<slot>为vue的内置标签:用于给组件定义一个插槽,在这个插槽里传入内容(可以是模板代码或者组件),达到动态改变组件的目的. v-slot指令:绑定内容到指定插槽,v-slot 只能添 ...
- java目前常用的几种定时任务
java目前常用的几种定时任务 JDK自带的Timer spring的Task Quartz elastic-job分布式定时任务 一.JDK自带的Timer Timer是jdk中提供的一个定时器工具 ...
- java开发在线下载功能,自动打开浏览器下载功能下载网络文件或图片
因为业务的需要,公司产品要求商品详情页面有个下载的功能 找了很多的方法,发现有的需要打开一个新窗口,而且在某些浏览器上不适用,所以继续寻找更好的方法 跟同事沟通后发现他那里有个下载的方法,不过是C#写 ...
- JS 与 jQery 的区别主要在于 DOM
//目前正在学习前端阶段,把知识点整理.保存下来以便日后查看 首先引入jQery: 需要先引入css,再引入js: jQery需要在js前引入,再引入框架,最后才是js的引入:css也相同,先引入框架 ...
- C#LeetCode刷题之#263-丑数(Ugly Number)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3862 访问. 编写一个程序判断给定的数是否为丑数.丑数就是只包含 ...
- 实型(浮点型):float、double
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include<stdlib. ...