[FJOI2016]建筑师
Posted lizehon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[FJOI2016]建筑师相关的知识,希望对你有一定的参考价值。
斯特林数和组合数的应用 , 写得很好的题解
注意到建筑高度不同且取满\([1,n]\)
把所有的建筑分成 \(A+B-1\) 个部分 , \(n\)是最高点 , 把除了 \(n\) 以外的 \(n-1\)个建筑放到 \(A+B-2\)个圆桌上
相当于从高往低插入 , 可以选择独占一桌 , 即形成一个高峰 ; 或者补充到某一桌(块)某一人(楼)旁边 , 也就不会被看到
然后\(A+B-2\)个部分要选出\(A-1\)个放在左边,\(B-1\)个放在右边
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define Debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){
register LL x=0,f=1;register char c=getchar();
while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
return f*x;
}
const int SS=50005;
const int N=205;
const int mod=1e9+7;
int S[SS][N],C[N][N];
int T,n,a,b;
inline int add(int x,int y){x+=y;return x>mod?x-mod:x;}
inline int mul(LL x,int y){x*=y;return x>mod?x%mod:x;}
int main(){
S[0][0]=S[1][1]=1;
for(int i=2;i<SS;i++) S[i][1]=S[i-1][1]*(i-1);
for(int i=2;i<SS;i++){
for(int j=1;j<N&&j<=i;j++)
S[i][j]=add(S[i-1][j-1],mul(S[i-1][j],i-1));
}
for(int i=0;i<N;i++) C[i][0]=1;
for(int i=1;i<N;i++){
for(int j=1;j<=i;j++)
C[i][j]=add(C[i-1][j],C[i-1][j-1]);
}
T=read();
while(T--){
n=read(),a=read(),b=read();
printf("%d\n",mul(S[n-1][a+b-2],C[a+b-2][a-1]));
}
}
以上是关于[FJOI2016]建筑师的主要内容,如果未能解决你的问题,请参考以下文章