您的位置:首页 > 大数据 > 人工智能

2012 Multi-University Training Contest 8

2014-03-15 21:21 375 查看
HDU4379

/*HDU 4372 组合数学
第一类stirling数+排列
题意:有n栋高楼,高度属于[1,n]区间,且各不相同,排成一排后,
从左边看,有L个,右边看,看到R个(高楼会把矮楼挡住),
问,在满足这个条件时,可能有多少的不同排列方式?
*/
/*我们能知道最高的楼一定能看见,这样左边能看见L-1个,右边能看到R-1个,
因为数字各不相同,这样,等于把n-1个不同的数字分成L-1+R-1组,每组中的最高的放在最左边(右边),剩下几个被挡住的,有(k-1)!种排列方式。
第一类stirling数的定义:
把n个元素集合分作k个环排列的方法
我们把这个定义转化一下:
环排列:每两个元素的相对位置是一定的,但是环是能够旋转的,对于一个i环,环排列数是i!/i,正好符合这道题目的
分好k组后,左边放置L-1组,最大的要从小到大排列
所以,最终答案是 S[N-1][L-1+R-1]*C[L-1][L-1+R-1]
*/
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define maxn 2000+5
#define mod 1000000007
#define LL long long
using namespace std;
LL C[maxn][maxn];
LL S[maxn][maxn];

void init(){
//    memset(S,0,sizeof(S));
for(LL i=0;i<maxn;i++) {S[i][0]=0;S[i][i]=1;}
for(LL i=1;i<maxn;i++){
for(LL j=1;j<=i;j++){
S[i][j]=(S[i-1][j-1]+(i-1)*S[i-1][j])%mod;
}
}
memset(C,0,sizeof(C));
C[0][0]=1;
for(LL i=1;i<maxn;i++){
C[i][0]=1;C[i][i]=1;
for(LL j=1;j<maxn;j++)
C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
}
//最终答案是 S[N-1][L-1+R-1]*C[L-1][L-1+R-1]
LL t,N,L,R;
int main(){
init();
cin>>t;
while(t--){
cin>>N>>L>>R;
LL ans=(S[N-1][L-1+R-1]*C[L-1+R-1][L-1])%mod;
cout<<ans<<endl;
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: