Bell数:
记Bn是包含n个元素的集合的划分方法的数目。
例如:B0=1,B1=1,B2=2,B3=5,B4=15,B5=52。
Bell数递推公式:B0=1,Bn+1=Σ(k=0->k=n) C(n,k)*Bk。
Stirling数在组合数中分为两类。
第一类Stirling数:
含正负值,其绝对值是包含n个元素的集合分作k个环排列的方法数。
递推公式:S(n,0)=0,S(1,1)=1,S(n,k)=S(n-1,k-1)+S(n-1,k)*(n-1)。
证明:
1.设{an}是k个子集中的一个子集,于是把{a1,a2,a3......an-1}划分成k-1个集合有S(n-1,k-1)个划分数。
2,如果{an}不是k个子集中的一个,那么an必定是和其他元素构成了一个子集,首先把{a1,a2,a3......an-1}划分成k个子集,共有S(n-1,k)种划分数,再把an插进这些划分数中有(n-1)种方案,所以是(n-1)*S(n-1,k)。
对1,2运用加法定理:得S(n,k)=S(n-1,k-1)+S(n-1,k)*(n-1)。
第二类Stirling数:
把含有n个元素的集合划分成k个非空子集的方案数。
递推公式:
S(n,n)=S(n,1)=1. S(n,k)=S(n-1,k-1)+k*S(n-1,k)。(n>1,k>=1)
证明方法和第一类Stirling数类似。
结合Bell数和第二类Stirling数的定义,显然:Bn=Σ(k=1 -> k=n)S(n,k)
Bell数和第二类Stirling数可以通过构建Bell三角形求解,构建方法如下:
1.第一行第一项是1,a[1,1]=1.
2.对于n>1,满足:a[n,1]=a[n-1,n-1].
3.对于m,n>1,第n行第m项满足:a[n,m]=a[n,m-1]+a[n-1,m-1]。
结果如下:
1
1 2
2 3 5
5 7 10 15
15 20 27 37 52
.................................................
每行首项都是Bell数,每行之和是第二类Stirling数。
~~~~
Bell数 模板题:
UVA 10844
Little Joan has N blocks,all of them of different sizes. He is playing to build cities in the beach. A city
is just a collection of buildings.
A single block over the sand can be considered as a building. Then he can construct higher buildings
by putting a block above any other block. At most one block can be put immediately above any other
block. However he can stack several blocks together to construct a building. However, its not allowed
to put bigger blocks on top of smaller ones, since the stack of blocks may fall. A block can be speci ed
by a natural number that represents its size.
It doesn't matter the order among buildings. That is:
1 3
2 4
is the same con guration as:
3 1
4 2
Your problem is to compute the number of possible different cities using N blocks. We say that
#(N) gives the number of different cities of size N. If N = 2, for instance, there are only two possible
cities:
City #1:
1 2
In this city both blocks of size 1 and 2 are put over the sand.
City #2:
1
2
In this city block of size 1 is over block is size 2, and block of size 2 is over the sand.
So, #(2) = 2.
Input
A sequence of non-negative integer numbers, each of one in different line. All of them but the last one
are natural numbers. The last one is 0 and means the end. Each natural number is less than 900.
Output
For each natural number I in the input, you must write a line with the pair of numbers I, #(I).
Sample Input
2
3
0
Sample Output
2, 2
3, 5
分析:
用N块积木来盖建筑群可以理解成把一个大小为N的集合分成若干个不相交的子集。这符合Bell数的定义,本题可预处理Bell三角形之后以O(1)输出答案。
AC code:
#include<bits/stdc++.h> using namespace std; typedef unsigned long long int64; int64 m=1e10; struct Bigint{ int l; int64 s[200]; void read(int64 x) { l=-1; memset(s,0,sizeof(s)); do{ s[++l]=x%m; x/=m; }while(x); } void print() { printf("%llu",s[l]); for(int i=l-1;i>=0;i--) { printf("%010llu",s[i]); } } }dp[2][1000],ans[1000]; Bigint operator+(Bigint a,Bigint b) { a.l=max(a.l,b.l);int64 d=0; for(int i=0;i<=a.l;i++) { a.s[i]+=d+b.s[i]; d=a.s[i]/m; a.s[i]%=m; } if(d) a.s[++a.l]=d; return a; } int n; void getans(int id,int n) { int i=id^1; for(int j=1;j<=n;j++) { dp[id][j+1]=dp[i][j]+dp[id][j]; } } void work() { dp[1][1].read(1); ans[2]=dp[0][1]=ans[1]=dp[1][1]; for(int i=2;i<=900;i++) { getans(i&1,i); dp[(i&1)^1][1]=ans[i+1]=dp[i&1][i]; } } int main() { //freopen("input.txt","r",stdin); work(); while(~scanf("%d",&n)&&n) { printf("%d, ",n); ans[n+1].print(); printf("\n"); } return 0; }