第一二类斯特林数,bell数

一.第二类Stirling数

        定理:第二类Stirling数S(p,k)计数的是把p元素集合划分到k个不可区分的盒子里且没有空盒子的划分个数。

        证明:元素在拿些盒子并不重要,唯一重要的是各个盒子里装的是什么,而不管哪个盒子装了什么。

        递推公式有:S(p,p)=1 (p>=0)         S(p,0)=0  (p>=1)         S(p,k)=k*S(p-1,k)+S(p-1,k-1)   (1<=k<=p-1) 。考虑将前p个正整数,1,2,.....p的集合作为要被划分的集合,把

{1,2,.....p}分到k个非空且不可区分的盒子的划分有两种情况:

       (1)那些使得p自己单独在一个盒子的划分,存在有S(p-1,k-1)种划分个数

       (2)那些使得p不单独自己在一个盒子的划分,存在有 k*S(p-1,k)种划分个数

        考虑第二种情况,p不单独自己在一个盒子,也就是p和其他元素在一个集合里面,也就是说在没有放p之前,有p-1个元素已经分到了k个非空且不可区分的盒子里面(划

分个数为S(p-1,k),那么现在问题是把p放在哪个盒子里面呢,有k种选择,所以存在有k*S(p-1,k)。

       模板:

[cpp]  view plain  copy
  1. long long s[maxn][maxn];//存放要求的Stirling数  
  2. const long long mod=1e9+7;//取模  
  3.   
  4. void init()//预处理  
  5. {  
  6.     memset(s,0,sizeof(s));  
  7.     s[1][1]=1;  
  8.     for(int i=2;i<=maxn-1;i++)  
  9.         for(int j=1;j<=i;j++)  
  10.     {  
  11.         s[i][j]=s[i-1][j-1]+j*s[i-1][j];  
  12.         if(s[i][j]>=mod)  
  13.             s[i][j]%=mod;  
  14.     }  
  15. }  

       注意:要用long long类型,当元素个数>20,就超int类型了。

       扩展:k! *S(p,k) 计数的是把p元素集合划分到k个可区分的盒子里且没有空盒子的划分个数。

 

二.Bell数

        定理:Bell数B(p)是将p元素集合分到非空且不可区分盒子的划分个数(没有说分到几个盒子里面)。

        B(p)=S(p,0)+S(p,1)+.....+S(p,k) 

       所以要求Bell数就要先求出第二类Stiring数。

三.第一类Stirling数

       定理:第一类Stirling数s(p,k)计数的是把p个对象排成k个非空循环排列的方法数。

       证明:把上述定理叙述中的循环排列叫做圆圈。递推公式为:

       s(p,p)=1 (p>=0)    有p个人和p个圆圈,每个圆圈就只有一个人

       s(p,0)=0 (p>=1)    如果至少有1个人,那么任何的安排都至少包含一个圆圈

       s(p,k)=(p-1)*s(p-1,k)+s(p-1,k-1)

       设人被标上1,2,.....p。将这p个人排成k个圆圈有两种情况。第一种排法是在一个圆圈里只有标号为p的人自己,排法有s(p-1,k-1)个。第二种排法中,p至少和另一个人在一

个圆圈里。这些排法可以通过把1,2....p-1排成k个圆圈再把p放在1,2....p-1任何一人的左边得到,因此第二种类型的排法共有(p-1)*s(p-1,k)种排法。

       在证明中我们所做的就是把{1,2,...,p}划分到k个非空且不可区分的盒子,然后将每个盒子中的元素排成一个循环排列。

       模板:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. long long s[maxn][maxn];//存放要求的第一类Stirling数  
  2. const long long mod=1e9+7;//取模  
  3.   
  4. void init()//预处理  
  5. {  
  6.     memset(s,0,sizeof(s));  
  7.     s[1][1]=1;  
  8.     for(int i=2;i<=maxn-1;i++)  
  9.         for(int j=1;j<=i;j++)  
  10.     {  
  11.         s[i][j]=s[i-1][j-1]+(i-1)*s[i-1][j];  
  12.         if(s[i][j]>=mod)  
  13.             s[i][j]%=mod;  
  14.     }  
  15. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值