poj 3088 Push Botton Lock (dp+组合数学|斯特林数)

来源:互联网 发布:三星专用软件下载 编辑:程序博客网 时间:2024/06/07 12:46

Push Botton Lock
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 1526 Accepted: 967

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

3343

Sample Output

1 3 252 4 1493 3 25

Source

Greater New York 2006

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


题解:dp+组合数学|斯特林数

f[i][1]=c[i][n] c表示组合数

f[i][i]=a[i][n] a表示排列数

f[i][j]=sigma f[i-k][j-1]*c[k][n-(i-k)]  我们考虑最后一个盒子放几个和放哪些。

#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<cmath>#define N 103#define LL long longusing namespace std;LL f[N][N];int n;LL calc(int x,int y){LL ans=1;for (int i=y;i>=y-x+1;i--) ans*=(LL)i;return (LL)ans;}LL c(int x,int y){LL ans=1;for (int i=y;i>=y-x+1;i--) ans*=(LL)i;for (int i=1;i<=x;i++) ans/=(LL)i;return ans;}int main(){   int t;   scanf("%d",&t);   for (int T=1;T<=t;T++){     scanf("%d",&n);     memset(f,0,sizeof(f));     LL ans=0;     f[1][1]=calc(1,n); ans+=f[1][1];     for (int i=2;i<=n;i++)     {      f[i][1]=c(i,n); ans+=f[i][1];      for (int j=2;j<=i-1;j++)      {        for (int k=1;k<=n;k++)         { if (i-k==0) break;          f[i][j]+=f[i-k][j-1]*c(k,n-(i-k));            }        ans+=f[i][j];      }      f[i][i]=calc(i,n),ans+=f[i][i];      }      printf("%d %d %lld\n",T,n,ans);   }}

斯特林数:斯特林数出现在许多组合枚举问题中. 对第一类斯特林数 StirlingS1[n,m], 给出恰包含 m 个圈的 n 个元素 的排列数目. 斯特林数满足母函数关系 . 注意某些 的定义与 Mathematica 中的不同,差别在于因子 . 第二类斯特林数 StirlingS2[n,m]给出把 n 个可区分小球分配到m个不可区分的的盒子,且盒子没有空盒子的方法的数量. 它们满足关系 . 划分函数 PartitionsP[n]给出把整数 n 写为正整数的和,不考虑顺序的方法的数目. PartitionsQ[n]给出把整数 n 写为正整数的和,并且和中的整数是互不相同的 写法的数目
  设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)种方法。

从ATP神犇那里get到一个新的想法:

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