第一类斯特林数+组合数 - Pole Arrangement(UVA 1638)

传送门

Analysis

大多数题解都提供的是dp做法
这里推广一个不知哪个神犇想出来的神仙做法
O(1)计算可还行?


除了最高的那根杆,左边还能看到 l - 1 根,右边还能看到 r - 1 根。
把这些杆子和他们挡住的杆子看做一个圆排列,那么共有 [ l + r − 2 n − 1 ] [^{n-1}_{l+r-2}] [l+r2n1]种分配方案。
左边要选 l − 1 l-1 l1
故答案为 a n s = [ l + r − 2 n − 1 ] ∗ ( l − 1 l + r − 2 ) ans=[^{n-1}_{l+r-2}]*(_{l-1}^{l+r-2}) ans=[l+r2n1](l1l+r2)

可以这样来意会:
对于一段区间(当前最高的杆子和它后面低于它的杆子),长度为k,其最高的杆子已经确定,那么后面就有 ( k − 1 ) ! (k-1)! (k1)!种排列方式,这和圆排列恰好神奇的吻合
然后从 l + r − 2 l+r-2 l+r2中选取 l − 1 l-1 l1个圆排列放在左边,一定可以找出一种且仅有一种排列方式,使得其满足,从左往右,最高杆子的高度依次递增。对于右边,同理。


Code

注意第一类斯特林数的计算,外层循环从0开始
S1(0,0)=1
(从0个中选0个方案数为1)

#include<bits/stdc++.h>
#define re register
#define int long long
using namespace std;
typedef long long ll;
ll S1[210][210],C[210][210];
void pre_work(){
	C[0][0]=1;
	for(re int i=1;i<=205;++i){
		C[i][i]=C[i][0]=1;
		for(re int j=1;j<i;++j){
			C[i][j]=(C[i-1][j-1]+C[i-1][j]);
		}
	}
	for(re int i=0;i<=205;++i){
		S1[i][i]=1;
		for(re int j=1;j<i;++j){
			S1[i][j]=(S1[i-1][j-1]+(i-1)*S1[i-1][j]);
		}
	}
}
signed main(){
	int T;
	scanf("%lld",&T);
	pre_work();
	while(T--){
		int n,l,r;
		scanf("%lld%lld%lld",&n,&l,&r);
		printf("%lld\n",S1[n-1][l+r-2]*C[l+r-2][l-1]);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值