传送门

首先对于高度为\(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]建筑师的更多相关文章

  1. 【LG4609】[FJOI2016]建筑师

    [LG4609][FJOI2016]建筑师 题面 洛谷 题解 (图片来源于网络) 我们将每个柱子和他右边的省略号看作一个集合 则图中共有\(a+b-2\)个集合 而原来的元素中有\(n-1\)个(除去 ...

  2. [洛谷P4609] [FJOI2016]建筑师

    洛谷题目链接:[FJOI2016]建筑师 题目描述 小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 \(n\) 个建筑,每个建筑的高度是 \(1\) 到 \(n\) 之间的一 ...

  3. Luogu P4609 [FJOI2016]建筑师&&CF 960G Bandit Blues

    考虑转化题意,我们发现其实就是找一个长度为\(n\)的全排列,使得这个排列有\(A\)个前缀最大值,\(B\)个后缀最大值,求方案数 我们考虑把最大值拎出来单独考虑,同时定义一些数的顺序排列为单调块( ...

  4. [FJOI2016]建筑师

    题目描述 小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 n 个建筑,每个建筑的高度是 1 到 n 之间的一个整数. 小 Z 有很严重的强迫症,他不喜欢有两个建筑的高度相同. ...

  5. 洛谷 P4609: [FJOI2016] 建筑师

    本省省选题是需要做的. 题目传送门:洛谷P4609. 题意简述: 求有多少个 \(1\) 到 \(N\) 的排列,满足比之前的所有数都大的数正好有 \(A\) 个,比之后的所有数都大的数正好有 \(B ...

  6. 洛谷P4609 [FJOI2016]建筑师 【第一类斯特林数】

    题目链接 洛谷P4609 题解 感性理解一下: 一神带\(n\)坑 所以我们只需将除了\(n\)外的\(n - 1\)个元素分成\(A + B - 2\)个集合,每个集合选出最大的在一端,剩余进行排列 ...

  7. 洛谷P4609 [FJOI2016]建筑师(第一类斯特林数+组合数)

    题面 洛谷 题解 (图片来源于网络,侵删) 以最高的柱子\(n\)为分界线,我们将左边的一个柱子和它右边的省略号看作一个圆排列,右边的一个柱子和它左边的省略号看作一个圆排列,于是,除了中间的最高的柱子 ...

  8. Luogu4609 FJOI2016 建筑师 第一类斯特林数

    题目传送门 题意:给出$N$个高度从$1$到$N$的建筑,问有多少种从左往右摆放这些建筑的方法,使得从左往右看能看到$A$个建筑,从右往左看能看到$B$个建筑.$N \leq 5 \times 10^ ...

  9. Luogu4609 FJOI2016建筑师(斯特林数)

    显然排列中的最大值会将排列分成所能看到的建筑不相关的两部分.对于某一边,将所能看到的建筑和其遮挡的建筑看成一个集合.显然这个集合内最高的要排在第一个,而剩下的建筑可以随便排列,这相当于一个圆排列.同时 ...

随机推荐

  1. pytorch张量数据索引切片与维度变换操作大全(非常全)

    (1-1)pytorch张量数据的索引与切片操作1.对于张量数据的索引操作主要有以下几种方式:a=torch.rand(4,3,28,28):DIM=4的张量数据a(1)a[:2]:取第一个维度的前2 ...

  2. python中对闭包的理解

    运行环境声明:本人的代码在sublime text 3中写的,可以Ctrl+b运行.python版本是python3.6.如果您直接运行的,请自觉加入if __name__ == '__main__' ...

  3. Xshell 5的快捷键

    Xshell 5的快捷键 1. 点击下图中的按钮查看快捷键: 2. 快捷键备忘录: 序号 功能 快捷键 备注 1 在窗口和撰写栏之间切换 Alt+I   2 全屏 Alt+Enter   3     ...

  4. Linux centosVMware Vim介绍、vim颜色显示和移动光标、vim一般模式下移动光标、vim一般模式下复制、剪切和粘贴

    一.Vim介绍 vim 是一款功能强大的文本编辑器,是vi的升级版,带有颜色显示, 默认有三种模式:一般模式, 命令模式,  编辑模式   安装Vim [root@davery ~]# vim /et ...

  5. Java - lastIndexOf() 方法

    此方法含头不含尾,如获取方法名 add 需要 +1

  6. Day1-E-BZOJ1293

    Description 小西有一条很长的彩带,彩带上挂着各式各样的彩珠.已知彩珠有N个,分为K种.简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置).某些坐标上可以没有彩珠,但多个彩 ...

  7. ReentrantLock售票的例子&sleep和wait的区别锁可重入是什么(笔记)

    1 sleep 在哪里都可以用 调用Thread.sleep()但是 wait方法只能在同步方法和同步代码块中使用 wait也就是使得该线程成为阻塞状态(注意这里阻塞不是书本操作系统下的while循环 ...

  8. 线程高级篇-Lock锁实现生产者-消费者模型

    Lock锁介绍: 在java中可以使用 synchronized 来实现多线程下对象的同步访问,为了获得更加灵活使用场景.高效的性能,java还提供了Lock接口及其实现类ReentrantLock和 ...

  9. SciPy 常量

    章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...

  10. SciPy fftpack(傅里叶变换)

    章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...