[题解] LuoguP4609 [FJOI2016]建筑师
首先对于高度为\(n\)的建筑,他的左边有\(A-1\)个建筑能被看到,右边有\(B-1\)个建筑能被看到,这两者类似,所以先来看左边。
一个建筑将会遮挡住它后面的高度比它矮的建筑,直到一个高度比他高的出现,所以我们不妨按这样分段看一下,例如下面这个排列
3 2 4 1 5 7 6
分段后会变成
[3 2][4 1][5][7 6]
我们要求的就是高度为\(n\)的建筑左边有\(A-1\)段,右边有\(B-1\)段的方案数。
不难想到讲每一段看成一个圆排列,然后讲最大的一个元素作为排列的第一个,然后从左到右形成一段。
例如这个圆排列\((1,5,3)\),将\(5\)提到第一个后会变成\([5,3,1]\),这样就对应了上面说的一段。
那么我们只要把\(1...n-1\)这\(n-1\)个数安排到\(A+B-2\)个圆排列里,然后在\(n\)的左边放\(A-1\)个圆排列,其中这\(A-1\)个 圆排列按排列中的最大数做关键字从小到大放就好了,右边\(B-1\)个排列按从大到小放。
这样答案就是\(s(n-1,A+B-2) \times C(A+B-2,A-1)\)
其中\(C(n,r)\)表示组合数,\(s(n,k)\)表示第一类Stirling数,预处理出第一类斯特林数和组合数,\(O(1)\)的回答就好了
\(Code:\)
#include <bits/stdc++.h>
using namespace std;
const int N=50010,P=1e9+7;
inline int add(int x,int y){return (x+=y)>=P?x-P:x;}
inline int sub(int x,int y){return (x-=y)<0?x+P:x;}
int s[N][310],C[310][310];
int main()
{
s[0][0]=1;
for(int i=1;i<=50000;i++)
for(int j=1;j<=min(i,200);j++)
s[i][j]=add(1ll*s[i-1][j]*(i-1)%P,s[i-1][j-1]);
C[0][0]=1;
for(int i=1;i<=200;i++)
{
C[i][0]=C[i][i]=1;
for(int j=1;j<i;j++)
C[i][j]=add(C[i-1][j],C[i-1][j-1]);
}
int _;scanf("%d",&_);while(_--)
{
int n,A,B; scanf("%d%d%d",&n,&A,&B);
printf("%d\n",1ll*s[n-1][A+B-2]*C[A+B-2][A-1]%P);
}
return 0;
}
[题解] LuoguP4609 [FJOI2016]建筑师的更多相关文章
- 【LG4609】[FJOI2016]建筑师
[LG4609][FJOI2016]建筑师 题面 洛谷 题解 (图片来源于网络) 我们将每个柱子和他右边的省略号看作一个集合 则图中共有\(a+b-2\)个集合 而原来的元素中有\(n-1\)个(除去 ...
- [洛谷P4609] [FJOI2016]建筑师
洛谷题目链接:[FJOI2016]建筑师 题目描述 小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 \(n\) 个建筑,每个建筑的高度是 \(1\) 到 \(n\) 之间的一 ...
- Luogu P4609 [FJOI2016]建筑师&&CF 960G Bandit Blues
考虑转化题意,我们发现其实就是找一个长度为\(n\)的全排列,使得这个排列有\(A\)个前缀最大值,\(B\)个后缀最大值,求方案数 我们考虑把最大值拎出来单独考虑,同时定义一些数的顺序排列为单调块( ...
- [FJOI2016]建筑师
题目描述 小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 n 个建筑,每个建筑的高度是 1 到 n 之间的一个整数. 小 Z 有很严重的强迫症,他不喜欢有两个建筑的高度相同. ...
- 洛谷 P4609: [FJOI2016] 建筑师
本省省选题是需要做的. 题目传送门:洛谷P4609. 题意简述: 求有多少个 \(1\) 到 \(N\) 的排列,满足比之前的所有数都大的数正好有 \(A\) 个,比之后的所有数都大的数正好有 \(B ...
- 洛谷P4609 [FJOI2016]建筑师 【第一类斯特林数】
题目链接 洛谷P4609 题解 感性理解一下: 一神带\(n\)坑 所以我们只需将除了\(n\)外的\(n - 1\)个元素分成\(A + B - 2\)个集合,每个集合选出最大的在一端,剩余进行排列 ...
- 洛谷P4609 [FJOI2016]建筑师(第一类斯特林数+组合数)
题面 洛谷 题解 (图片来源于网络,侵删) 以最高的柱子\(n\)为分界线,我们将左边的一个柱子和它右边的省略号看作一个圆排列,右边的一个柱子和它左边的省略号看作一个圆排列,于是,除了中间的最高的柱子 ...
- Luogu4609 FJOI2016 建筑师 第一类斯特林数
题目传送门 题意:给出$N$个高度从$1$到$N$的建筑,问有多少种从左往右摆放这些建筑的方法,使得从左往右看能看到$A$个建筑,从右往左看能看到$B$个建筑.$N \leq 5 \times 10^ ...
- Luogu4609 FJOI2016建筑师(斯特林数)
显然排列中的最大值会将排列分成所能看到的建筑不相关的两部分.对于某一边,将所能看到的建筑和其遮挡的建筑看成一个集合.显然这个集合内最高的要排在第一个,而剩下的建筑可以随便排列,这相当于一个圆排列.同时 ...
随机推荐
- pytorch张量数据索引切片与维度变换操作大全(非常全)
(1-1)pytorch张量数据的索引与切片操作1.对于张量数据的索引操作主要有以下几种方式:a=torch.rand(4,3,28,28):DIM=4的张量数据a(1)a[:2]:取第一个维度的前2 ...
- python中对闭包的理解
运行环境声明:本人的代码在sublime text 3中写的,可以Ctrl+b运行.python版本是python3.6.如果您直接运行的,请自觉加入if __name__ == '__main__' ...
- Xshell 5的快捷键
Xshell 5的快捷键 1. 点击下图中的按钮查看快捷键: 2. 快捷键备忘录: 序号 功能 快捷键 备注 1 在窗口和撰写栏之间切换 Alt+I 2 全屏 Alt+Enter 3 ...
- Linux centosVMware Vim介绍、vim颜色显示和移动光标、vim一般模式下移动光标、vim一般模式下复制、剪切和粘贴
一.Vim介绍 vim 是一款功能强大的文本编辑器,是vi的升级版,带有颜色显示, 默认有三种模式:一般模式, 命令模式, 编辑模式 安装Vim [root@davery ~]# vim /et ...
- Java - lastIndexOf() 方法
此方法含头不含尾,如获取方法名 add 需要 +1
- Day1-E-BZOJ1293
Description 小西有一条很长的彩带,彩带上挂着各式各样的彩珠.已知彩珠有N个,分为K种.简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置).某些坐标上可以没有彩珠,但多个彩 ...
- ReentrantLock售票的例子&sleep和wait的区别锁可重入是什么(笔记)
1 sleep 在哪里都可以用 调用Thread.sleep()但是 wait方法只能在同步方法和同步代码块中使用 wait也就是使得该线程成为阻塞状态(注意这里阻塞不是书本操作系统下的while循环 ...
- 线程高级篇-Lock锁实现生产者-消费者模型
Lock锁介绍: 在java中可以使用 synchronized 来实现多线程下对象的同步访问,为了获得更加灵活使用场景.高效的性能,java还提供了Lock接口及其实现类ReentrantLock和 ...
- SciPy 常量
章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...
- SciPy fftpack(傅里叶变换)
章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...