[FJOI2016]建筑师

[Luogu4609]

斯特林数和组合数的应用 , 写得很好的题解
注意到建筑高度不同且取满\([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]));
    }
}

转载于:https://www.cnblogs.com/lizehon/p/10585482.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值