Bell数和Stirling数

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;
}
View Code

猜你喜欢

转载自www.cnblogs.com/cautx/p/11413680.html
今日推荐