HDU 4372

想了很久,终于想到了。。。。

向后看到F,向前看到B,假如把N-1个楼分成F+B个组,则把每个组最高的楼作为看到的楼,那么,其实在确定每一组的最高楼时,左边或右边的最高楼的顺序已经确定了。由于是排列数,联想到第一类斯特灵数,即可以顺利解决。那么,分成F+B个组后,选出B个组放在右边(最高楼的右边)即可。

注意在求组合数时,不要用逆元,可以使用递推公式
C(N,K)=C(n-1,k)+C(n-1,k-1);

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL __int64
#define MOD 1000000007
#define N 2000
using namespace std;

LL str[N+5][N+5];
LL cnk[N+5][N+5];

void initial(){
	LL x,y;
	for(LL i=0;i<=N;i++){
		for(LL j=0;j<=i;j++){
			if(j==0)
			cnk[i][j]=1;
			else if(i==j) cnk[i][j]=1;
			else{
		//		cnk[i][j]=(cnk[i][j-1]*(i-j+1))%MOD;
		//		exgcd(j,MOD,x,y);
		//		cnk[i][j]=((cnk[i][j]*x)%MOD+MOD)%MOD;
				cnk[i][j]=(cnk[i-1][j-1]+cnk[i-1][j])%MOD;
			}
			if(i==j)
			str[i][j]=1;
			else if(j==0)
			str[i][j]=0;
			else{
				str[i][j]=((str[i-1][j]*(i-1))%MOD+str[i-1][j-1])%MOD;
			}
		}
	}
}

int main(){
	initial();
	int T;
	LL n,f,b,ans;
	scanf("%d",&T);
	while(T--){
		scanf("%I64d%I64d%I64d",&n,&f,&b);
		ans=(str[n-1][f+b-2]*cnk[f+b-2][b-1])%MOD;
		printf("%I64d\n",ans);
	}
	return 0;
}

  

时间: 2024-10-15 02:58:50

HDU 4372的相关文章

hdu 4372 第一类stirling数的应用/。。。好题

1 /** 2 大意: 给定一系列楼房,都在一条水平线上,高度从1到n,从左侧看能看到f个, 从右侧看,能看到b个,问有多少种这样的序列.. 3 思路: 因为肯定能看到最高的,,那我们先假定最高的楼房位置确定,那么在其左边还有f-1个能看见,在其右边还有b-1个,能看见..所以可以这样将题目转化: 将除最高楼之外的n-1个楼,分成f-1+b-1 组,在最高楼左边f-1 组,在其右边b-1组,那么分成f-1+b-1 组 就是第一类Stirling数.s[n-1][f-1+b-1]..左边f-1 组

HDU 4372 Count the Buildings:第一类Stirling数

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4372 题意: 有n栋高楼横着排成一排,各自的高度为1到n的一个排列. 从左边看可以看到f栋楼,从右边看可以看到b栋楼,并且高的楼会挡住低的楼. 问你这些楼有多少种排列方法. 题解: 由于高的楼会挡住低的楼,所以这些楼首先会被划分成f+b-2个区域(除去中间最高的楼),并且左边有f-1个,右边有b-1个. 对于一个区域(假设在左边),这个区域由若干栋楼组成,并且最高的楼一定在最左边. 那么,由一个区域

hdu 4372 第一类斯特林数

#include <cstdio> #include <iostream> #include <algorithm> #include <queue> #include <cmath> #include <cstring> #include <stack> #include <set> #include <map> #include <vector> using namespace st

HDU 4372 Count the Buildings(组合数学-斯特林数,组合数学-排列组合)

Count the Buildings Problem Description There are N buildings standing in a straight line in the City, numbered from 1 to N. The heights of all the buildings are distinct and between 1 and N. You can see F buildings when you standing in front of the

HDU 4372 Count the Buildings(组合数+斯特林数)

 题意:N座高楼,高度均不同且为1-N中的数,从前向后看能看到F个,从后向前看能看到B个,问有多少种可能的排列数. 思路:一开始想的是dp,但是数据范围达到2000,空间复杂度无法承受. 考虑以最高的楼分界,左边有f-1个递增的楼,右边有b-1个递减的楼,考虑将剩下n-1楼分为f+b-2组,规定每组中最高的在最左边,那么只需要 再从n-1组选出f-1组放到左边即可. 现在解决将n-1个楼分为f+b-2组每组最高的楼在左边的这个问题,这等价于将n-1个楼分为f+b-2个环的排列数,因为长度为n

暑假集训-合训第9场

ID Origin Title   8 / 22 Problem A HDU 4358 Boring counting 35 / 52 Problem B HDU 4359 Easy Tree DP? 31 / 79 Problem C HDU 4362 Dragon Ball   1 / 2 Problem D HDU 4363 Draw and paint 18 / 56 Problem E HDU 4365 Palindrome graph   3 / 17 Problem F HDU 4

【Stirling Number I】

hdu 4372 Count the Buildings 推荐这位小哥的,我觉得人家说的灰常的好. 注意数据范围,n,f,b均在(0,2000]范围内,而第一斯特林数的数组范围却是s[2000+5][2000+5]的(你要是开4000会内存超限),所以要加一个对(f+b-2)的判断,否则C++过不了,G++是能过的.亲身实践,虽然不知道G++为什么这么鲁棒... 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdli

概率与期望,组合

1.一个图论套路,结合之前的小知识(枚举子集) 例:Online judge 1268,Online judge 1396 询问一个图连通的方案数时,可令Dp一维为图是否连通,另一维是图的二进制表示(完全图可简化为点的个数),从而$Dp[x][0]$可通过$Dp[y][1]$来转移$y\subset x$ 具体来说,可令$x$中任意一个点为定点,枚举其中包含的联通块,同时其他点与该联通块之间不会有线段连接,按照题意列出方程可做到不重不漏.之后通过全集求出$Dp[x][1]$ #include <

hdu 1025 dp 最长上升子序列

1 //Accepted 4372 KB 140 ms 2 //dp 最长上升子序列 nlogn 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 using namespace std; 7 const int imax_n = 500005; 8 int dp[imax_n]; 9 int d[imax_n]; 10 int a[imax_n]; 11 int n; 12 int len