zoukankan      html  css  js  c++  java
  • HDU4372 Count the Buildings

    Description

    现在有一列楼,共 (n) 个,从前面看是 (f) 个,从后面看有 (b) 个,楼的高度是一个排列

    这里能看见得满足上升子序列

    求有多少种的排列满足条件

    (n,f,ble 2000)

    Solution

    一定能看到最高的那个楼,所以该正反的序列就都以高度为 (n) 的为结尾

    然后就是在剩下的 (n-1) 个里面选 (b-1) 个构成下降序列扔后面,选 (f-1) 个构成上升序列扔前面

    所以这 (n) 个数被分组了,而且就直接是圆排列……

    再想上这几个组再组合一下可以分成前面的 (f-1) 个和后面的 (b-1) 个,所以

    [ans=inom {(b-1)+(f-1)} {f-1} imes S(n-1,(b-1)+(f-1)) ]

    (O(n^2)) 预处理斯特林数,和组合数(这里考虑到爆空间,我用了线性的……)

    Code

    #include<bits/stdc++.h>
    using namespace std;
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int mod=1e9+7;
    	const int N=4010;
    	int n,f,b,s[N][N],inv[N],fac[N];
    	inline int C(int n,int m){return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;}
    	inline void work()
    	{
    		n=read(); f=read(); b=read(); 
    		printf("%lld
    ",1ll*s[n-1][b+f-2]*C(b+f-2,f-1)%mod);
    		return ;
    	}
    	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    	signed main()
    	{
    		s[1][1]=1; inv[1]=inv[0]=fac[0]=1;
    		for(int i=1;i<N;++i) fac[i]=1ll*fac[i-1]*i%mod;
    		for(int i=2;i<N;++i) inv[i]=mod-1ll*mod/i*inv[mod%i]%mod;
    		for(int i=1;i<N;++i) inv[i]=1ll*inv[i-1]*inv[i]%mod;
    		for(int i=2;i<N;++i) for(int j=1;j<=i;++j) s[i][j]=add(s[i-1][j-1],1ll*(i-1)*s[i-1][j]%mod);
    		int T=read(); while(T--) work();
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    
  • 相关阅读:
    一种安全云存储方案设计(上)——基于二次加密的存储策略与加密图文混合检索
    lamda表达式导致运行时VerifyError
    编译原理:语法分析概述
    语音识别与 RNN-Transducer 概述
    通信原理基本概念
    追光捉影的自动机:2021 卓工实训小作文
    【实战】jsfinder+jsinfo-scan结合改造
    js基础记录
    qq、微信二次分享
    收藏链接
  • 原文地址:https://www.cnblogs.com/yspm/p/13387082.html
Copyright © 2011-2022 走看看