【POJ 3088】Push Botton Lock(dp+第二类斯特林数)

41 篇文章 0 订阅
Push Botton Lock
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 1528 Accepted: 969

Description

The Frobozz Magic Lock Company is in the business of manufacturing push button style combination door locks. A push button door lock consists of a number of push buttons B, (1 ≤ B ≤ 11), labeled “1” through “B”. The lock is opened by pressing the correct sequence of button combinations and then turning the doorknob. If the sequence of presses is correct, the door magically opens.

A combination consists of 1 or more buttons being pressed simultaneously. A sequence consists of a series of combinations. A sequence must have at least one combination. Once a button has been used in a combination, it may not be used again in the same sequence. In addition, it is not necessary to use all the buttons in a sequence. For example, for B = 8:

(1-2-3)(4)(7-8)

is a valid sequence with 3 combinations (1-2-3), (4), and (7-8). Note that buttons 5 and 6 are not used in this sequence.

(1-2-3)(2-4)(5-6)

is not a valid sequence, since button 2 appears in 2 combinations (1-2-3) and (2-4).

The CEO of Frobozz, J. Pierpont Flathead, wants you to write a program that determines the number of valid sequences possible for given values of B. The program must be able to process a list of lock orders (datasets) from customers and generate a report showing the order number, the value of B, and the number of valid sequences possible. This list will always contain at least one dataset, but no more than 100 datasets.

Reference Materials:


J. Pierpont Flathead

Input

The first line of input contains a single integer N, (1 ≤ N ≤ 100), representing the number of datasets that follow. Each dataset consists of a single line of data containing a single integer B, which is the number of buttons for the lock.

Output

For each dataset, display the dataset number, a blank, the value B, a blank, and the number of valid sequences.

Sample Input

3
3
4
3

Sample Output

1 3 25
2 4 149
3 3 25

Source

[Submit]   [Go Back]   [Status]   [Discuss]

Home Page   Go Back  To top

[题意][N个不同的数字,放到一些不同的BOX里面,数字你不必用完,Box的个数也是可变的.比如三个球,你可以只放一个BOX,也可以放二个或者三个,但是四个BOX那就不可能了.每个数字只能放到一个BOX里,问有多少种放法.]

【题解】【dp+第二类斯特林数】
【这道题算了好久都没有找到通式,不开森...】
【后来搜了下题解发现是斯特林数。】
【用c[i][j]表示在i个数里取j个的组合数;然后由于这j个可以放到1-j个集合中,所以f[j][k]表示再将选出的j个数分到k个集合中的分法;a[i]表示i个数的全排列】
【斯特林数】
 {第一类斯特林数 StirlingS1[n,m], 给出恰包含 m 个圈的 n 个元素 的排列数目. 斯特林数满足母函数关系 . 注意某些 的定义与 Mathematica 中的不同,差别在于因子 .
   第二类斯特林数 StirlingS2[n,m]给出把 n 个可区分小球分配到m个不可区分的的盒子,且盒子没有空盒子的方法的数量

设S(p,k)是斯特林数

S(p,k)的一个组合学解释是:将p个物体划分成k个非空的不可辨别的(可以理解为盒子没有编号)集合的方法数。

S(p,k)的递推公式是:

 S(p,k) = k*S(p-1,k) + S(p-1,k-1) ,1<= k <=p-1

边界条件

S(p,p) = 1 ,p>=0

S(p,0) = 0 ,p>=1

递推关系的说明:考虑第p个物品,p可以单独构成一个非空集合,此时前p-1个物品构成k-1个非空的不可辨别的集合,方法数为S(p-1,k-1);也可以前p-1种物品构成k个非空的不可辨别的集合,第p个物品放入任意一个中,这样有k*S(p-1,k)种方法。

第一类斯特林数和第二类斯特林数有相同的初始条件,但递推关系不同。}     ——引自百度百科

【方程:f[i][j]=[j!=0][j!=1]f[i-1][j-1]+f[i-1][j]*j(这里有点类似于整数划分)】
【最后计算时,按乘法原理和加法原理来搞】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll f[20][20],c[20][20],a[20];
int T,n[110],m;
inline void solve()
{
	for(int i=1;i<=m;++i)
	 for(int j=0;j<=i;++j)
	  if(j==0||j==i) c[i][j]=1;
	   else c[i][j]=c[i-1][j]+c[i-1][j-1];
	f[1][1]=1; f[1][0]=0;
	for(int i=2;i<=m;++i)
	 for(int j=0;j<=i;++j)
	  if(!j) f[i][j]=0;
	   else 
	    if(j==1) f[i][j]=1;
	     else f[i][j]=f[i-1][j]*j+f[i-1][j-1];
	a[1]=1;
	for(int i=2;i<=m;++i) a[i]=a[i-1]*i;
	return;
}
int main()
{
	int i,j;
	scanf("%d",&T);
	for(i=1;i<=T;++i) scanf("%d",&n[i]),m=max(m,n[i]);
	solve();
	for(int l=1;l<=T;++l)
	 {
	 	ll ans=0;
	 	for(i=1;i<=n[l];++i)
	 	 for(j=1;j<=i;++j)
	 	  ans+=c[n[l]][i]*f[i][j]*a[j];
	 	printf("%d %d %lld\n",l,n[l],ans);
	   }  
	return 0;
}

ZYF神奇的思路
  

附ATP和斯特林数有些相似的方法:
  

f[i][j]表示将i个不同的小球放到j个不同的盒子的方案数。

f[i][j]=f[i-1][j]*j+f[i-1][j-1]*(j+1)  f[i-1][j]*j表示把第i个小球放到已经分好的j个盒子中的任意一个中;f[i-1][j-1]*(j+1)表示第i个小球单独放在一个盒子中,这个盒子有(j+1)个不同的位置可以插入。

统计答案的时候ans+=f[i][j]*c(i,n)



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值