stirling数 小讲 【 理解 + 例题 】 ing...

    今天看到两位巨巨,都不敢直视了、、、自己已经那么弱了,却没有一点的动力、、、

第一类Stirling数是有正负的,其绝对值是n个元素的项目分作k个环排列的方法数目。常用的表示方法有s(n,k) , \left[\begin{matrix} n \\ k \end{matrix}\right]

换个较生活化的说法,就是有n个人分成k组,每组内再按特定顺序围圈的分组方法的数目。例如s(4,2)

  1. {A,B},{C,D}
  2. {A,C},{B,D}
  3. {A,D},{B,C}
  4. {A},{B,C,D}
  5. {A},{B,D,C}
  6. {B},{A,C,D}
  7. {B},{A,D,C}
  8. {C},{A,B,D}
  9. {C},{A,D,B}
  10. {D},{A,B,C}
  11. {D},{A,C,B}
  • 给定s(n,0)=0,s(1,1)=1,有递归关系s(n+1,k)=s(n,k-1) + n \; s(n,k)

递推关系的说明:考虑第n+1个物品,n+1可以单独构成一个非空循环排列,这样前n种物品构成k-1个非空循环排列,方法数为s(n,k-1);也可以前n种物品构成k个非空循环排列,而第n+1个物品插入第i个物品的左边,这有n*s(n,k)种方法。

第二类Stirling数n个元素的集定义k个等价类的方法数目。常用的表示方法有S(n,k) , S_n^{(k)} ,  \left\{\begin{matrix} n \\ k \end{matrix}\right\}

换个较生活化的说法,就是有n个人分成k组的分组方法的数目。例如有甲、乙、丙、丁四人,若所有人分成1组,只有所有人在同一组这个方法,因此S(4,1)=1;若所有人分成4组,只可以人人独立一组,因此S(4,4)=1;若分成2组,可以是甲乙一组、丙丁一组,或甲丙一组、乙丁一组,或甲丁一组、乙丙一组,或其中三人同一组另一人独立一组,即是:

  1. {A,B},{C,D}
  2. {A,C},{B,D}
  3. {A,D},{B,C}
  4. {A},{B,C,D}
  5. {B},{A,C,D}
  6. {C},{A,B,D}
  7. {D},{A,B,C}

因此S(4,2)=7

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

    以上摘自wiki百科,算是mark一下,纯数学,弄懂递推关系是重点,再做一两道题,应该差不多了吧、、、、

    例题:

    NOJ  1379   小球划分    链接: http://ac.nbutoj.com/Problem/view.xhtml?id=1379 

    该题就是简单的第二类stirling 数,即求 N 个东西放入 J 个盒子中,有多少种不同的方法(0 < J  <=  N)

    注:由于该OJ 故障,该代码不知是否AC,仅供参考、、

#include <stdio.h>

#define mod 10000

int s[1100][1100]; // s[i][j],表示把i 个东西放入j个盒子中的方法数
int ans[1100];  // ans[i] ,表示 i 个球一共的放法数

int main()
{
    s[1][1] = ans[1] = 1; // 初始化
    for(int i = 2; i <= 1000; i ++)
    {
        for(int j = 1; j <= i; j ++)
	{
            if(i == j || j == 1)
                 s[i][j] = 1;
            else
                s[i][j] = s[i - 1][j - 1] + j * s[i - 1][j];
            s[i][j] %= mod;
            ans[i] += s[i][j];
	}
	ans[i] %= mod;
    }
    int n;
    while(~scanf("%d", &n))
    {
	printf("%d\n", ans[n]);
    }
    return 0;
 }




   

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值