[Luogu4609][FJOI2016]建筑师

luogu

description

一个\(1...n\)的排列,其前缀最大值有\(A\)个,后缀最大值有\(B\)个,求满足要求的排列数。
一个位置\(i\)满足前缀最大当且仅当不存在\(j<i\)使得\(a_j>a_i\)。后缀最大亦然。
\(T\le2\times10^5,n\le5\times10^4,A,B\le100\)

sol

考虑\(n\)这个数。它一定既是前缀最大又是后缀最大,所以它的前面还有\(A-1\)个前缀最大,\(B-1\)个后缀最大。
考虑每个前缀/后缀最大值,它一定挡住了若干个数(可能是零个)使得它们不能成为前缀最大。不妨将其视作一个整体,其中最大的那个数是前缀/后缀最大值,且位置在最左/右边,其余的数可以随意排列。
这等价于把除了\(n\)以外的\(n-1\)个数分成\(A+B-2\)个环排列。而这就是第一类斯特林数的定义。
所以答案就是\(s(n-1,A+B-2)\times\binom{A+B-2}{A-1}\)。
\(O(n(A+B))\)预处理,然后\(O(1)\)回答。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
const int N = 50005;
const int M = 205;
const int mod = 1e9+7;
int S[N][M],C[M][M];
int main(){
    S[0][0]=1;
    for (int i=1;i<N;++i)
        for (int j=1;j<=i&&j<M;++j)
            S[i][j]=(1ll*S[i-1][j]*(i-1)+S[i-1][j-1])%mod;
    C[0][0]=1;
    for (int i=1;i<M;++i){
        C[i][0]=1;
        for (int j=1;j<=i;++j)
            C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
    }
    int Case=gi();while (Case--){
        int n=gi(),a=gi(),b=gi();
        printf("%lld\n",1ll*S[n-1][a+b-2]*C[a+b-2][a-1]%mod);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zhoushuyu/p/9484296.html

时间: 2024-08-05 04:09:31

[Luogu4609][FJOI2016]建筑师的相关文章

Luogu4609 FJOI2016 建筑师 第一类Stirling数

题目传送门 题意:给出$N$个高度从$1$到$N$的建筑,问有多少种从左往右摆放这些建筑的方法,使得从左往右看能看到$A$个建筑,从右往左看能看到$B$个建筑.$N \leq 5 \times 10^4 , A,B \leq 100$ 第一次看到第一类$Stirling$数有用emmm 考虑将某种方案中最高的建筑拿出来,将分成的两半中可以看得见的与被它挡住的建筑分成一个部分,如下 绿色的当然是最高的,剩下的两个部分分成了1,2,3三个部分.可以知道我们总共需要$A+B-2$这样的部分,而其中$A

[FJOI2016]建筑师(斯特林数)

[FJOI2016]建筑师 问题描述 小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 n 个建筑,每个建筑的高度是 1 到 n 之间的一个整数. 小 Z 有很严重的强迫症,他不喜欢有两个建筑的高度相同.另外小 Z 觉得如果从最左边(所有建筑都在右边)看能看到 A个建筑,从最右边(所有建筑都在左边)看能看到 B 个建筑,这样的建筑群有着独特的美感.现在,小 Z 想知道满足上述所有条件的建筑方案有多少种? 如果建筑 i 的左(右)边没有任何建造比它高,则建筑 i 可以从左(

[FJOI2016] 建筑师

题目描述 小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 nn 个建筑,每个建筑的高度是 11 到 nn 之间的一个整数. 小 Z 有很严重的强迫症,他不喜欢有两个建筑的高度相同.另外小 Z 觉得如果从最左边(所有建筑都在右边)看能看到 AA个建筑,从最右边(所有建筑都在左边)看能看到 BB 个建筑,这样的建筑群有着独特的美感.现在,小 Z 想知道满足上述所有条件的建筑方案有多少种? 如果建筑 ii 的左(右)边没有任何建造比它高,则建筑 ii 可以从左(右)边看到.两

P4609 [FJOI2016]建筑师

思路 裸的第一类斯特林数,思路和CF960G相同 预处理组合数和第一类斯特林数回答即可 代码 #include <cstdio> #include <cstring> #include <algorithm> #define int long long using namespace std; const long long MOD= 1e9+7; long long jc[300],inv[300],n,a,b,S_[50100][210]; long long po

[题解] [FJOI2016] 建筑师

题面 题解 题意所给即为前缀最大值有 \(A\) 种, 后缀最大值有 \(B\) 种 由于 \(n\) 是肯定为最大值的, 也就是说, 其他 \(A - 1\) 个前缀最大值都在 \(n\) 左边出现, \(B - 1\) 个后缀最大值都在 \(n\) 右边出现 那么每一种方案就相当于把 \(n\) 单独拿出来, 其他的分为 \(A + B - 2\) 组 若这一组的最大值是前缀最大值, 则这一组最高的必须要放在第一个, 其他的放在他后面随意排列 若这一组的最大值是后缀最大值, 则这一组最高的必

第一类斯特林数

第一类斯特林数大概是这样一个意思:首先从n排列中选出一个m圆排列,这个圆排列也可以理解为有一个位置元素固定的排列,其方案数显然为(m-1)!. 可以用来解决一下有特殊位置的计数问题. 例题 [FJOI2016]建筑师 首先找到最高的建筑作为分水岭后,剩下的位置可以如下划分成a-1+b-1个区间. 发现这a-1+b-1个区间第每一个都必须满足区间最大值放在最前面. 这个东西就可以用第一类斯特林数解决. https://www.cnblogs.com/zhouzhendong/p/Stirling-

企业诚意寻注册一级建筑师合作

企业诚意寻注册一级建筑师合作单位在浙江,为升级资质现需要2本证书挂靠有意向的朋友可随时联系,报销差旅等费用!肖经理:13379064440         QQ: 1748609036

FJOI2016 神秘数

题目大意 给定长为$N$一个序列,每次询问一个区间,求最小的不能表示为由区间内若干个(可以是$0$个)数的和的非负整数. 考虑一个可重集合$S$,设抽取$S$中若干个数相加无法得到的最小非负整数为$Ans_S$ 显然$Ans_{\emptyset}=1$ 当加入一个元素$x$时 当$x>Ans_S$时,原先的$Ans_S$仍然无法凑出来,所以答案不变 当$x\leq Ans_S$时,原先的$0,1...Ans_S-1$可表示为$x,x+1...Ans_S-1+x$由于$x\leq Ans_S-1

luogu4608 [FJOI2016]所有公共子序列问题

题目描述: luogu loj 题解: 序列自动机(?)+高精+普及dp. 这个是猫老师的序列自动机(字符串从1开始): void sol(char *s,int n,int t[N][53]) { memset(t[n],-1,sizeof(t[n])); for(int i=n-1;i>=0;i--) { memcpy(t[i],t[i+1],sizeof(t[i])); t[i][ci(s[i+1])] = i+1; } } 序列自动机 $t$数组记录在位置$i$的后面加字符$j$能到达的