组合数学 —— 斯特林数(Stirling)

2024-06-17 23:38

本文主要是介绍组合数学 —— 斯特林数(Stirling),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【第一类斯特林数】

1.定理

第一类斯特林数 S1(n,m) 表示的是将 n 个不同元素构成 m 个圆排列的数目。

2.递推式

设人被标上1,2,.....p,则将这 p 个人排成 m 个圆有两种情况:

  • 在一个圆圈里只有标号为 p 的人自己,排法有 S1(n-1,m-1) 个。
  • p 至少和另一个人在一个圆圈里。

这些排法通过把 1,2....n-1 排成 m 个圆再把 n 放在 1,2....n-1 任何一人左边得到,因此第二种类型排法共有 (n-1)*S1(n-1,m) 种。

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

综上,可得出第一类Stirling数定理:S1(n,m)=(n-1)*S1(n-1,m)+S1(n-1,m-1) (n>1,m>1)

边界条件:

  • S1(n,m)=1 (n>=0):有 n 个人和 n 个圆,每个圆只有一个人
  • S1(n,0)=0 (n>=1) :如果至少有 1 个人,那么任何的安排都至少包含一个圆

3.应用举例

第一类斯特林数除了可以表示升阶函数和降阶函数的系数之外还可以应用到一些实际问题上,比如很经典的解锁仓库问题。

问题说明:

有 n 个仓库,每个仓库有两把钥匙,共 2n 把钥匙。同时又有 n 位官员。

求:①如何放置钥匙使得所有官员都能够打开所有仓库?(只考虑钥匙怎么放到仓库中,而不考虑官员拿哪把钥匙。)

       ②如果官员分成 m 个不同的部,部中的官员数量和管理的仓库数量一致。那么有多少方案使得,同部的所有官员可以打开所有本部管理的仓库,而无法打开其他部管理的仓库?(同样只考虑钥匙的放置。)

分析:

① 打开仓库将钥匙放入仓库构成一个环:1号仓库放2号钥匙,2号仓库放3号钥匙……n号仓库放1号钥匙,这种情况相当于钥匙和仓库编号构成一个圆排列方案数是 (n-1)! 种。

② 对应的将 n 个元素分成 m 个圆排列,方案数就是第一类斯特林数 S1(n,m),若要考虑官员的情况,只需再乘上 n! 即可。

4.算法实现

const int mod=1e9+7;//取模
LL s[N][N];//存放要求的第一类Stirling数
void init(){memset(s,0,sizeof(s));s[1][1]=1;for(int i=2;i<=N-1;i++){for(int j=1;j<=i;j++){s[i][j]=s[i-1][j-1]+(i-1)*s[i-1][j];if(s[i][j]>=mod)s[i][j]%=mod;}}
}

【第二类斯特林数】

1.定理

第二类斯特林数 S2(n,m) 表示的是把 n 个不同元素划分到 m 个集合的方案数。

2.递推式

元素在哪些集合并不重要,唯一重要的是各集合里装的是什么,而不管哪个集合装了什么。

考虑将前 n 个正整数,{1,2,...,n} 的集合作为要被划分的集合,把 {1,2,...,n} 分到 m 个非空且不可区分的集合的划分有两种情况:

  • 那些使得 n 自己单独在一个集合的划分,存在有 S2(n-1,m-1) 种划分个数
  • 那些使得 n 不单独自己在一个盒子的划分,存在有 m*S2(n-1,m) 种划分个数

考虑第二种情况,n 不单独自己在一个盒子,也就是 n 和其他元素在一个集合里面,也就是说在没有放 n 之前,有 n-1 个元素已经分到了m 个非空且不可区分的盒子里面(划分个数为 S2(n-1,m)),那么现在问题是把 n 放在哪个盒子里面,此时有 m 种选择,所以存在有 m*S2(n-1,m)

综上,可得出第二类斯特林数定理: S2(n,m)=m*S2(n-1,m)+S2(n-1,m-1) (1<=m<=n-1)

边界条件:\left\{\begin{matrix}S2(n,m)=1 ,n>=0 \\S2(n,0)=0,n>=1 \end{matrix}\right. 

3.应用举例

第二类斯特林数主要是用于解决组合数学中的放球模型,主要是针对于球之前有区别的放球模型:

1)n 个不同的球,放入 m 个无区别的盒子,不允许盒子为空。

     方案数:S2(n,m),与第二类斯特林数的定义一致。

2)n 个不同的球,放入 m 个有区别的盒子,不允许盒子为空。

     方案数:m!*S2(n,m),因盒子有区别,乘上盒子的排列即可。

3)n 个不同的球,放入 m 个无区别的盒子,允许盒子为空。

     方案数:,枚举非空盒的数目即可。

4)n 个不同的球,放入 m 个有区别的盒子,允许盒子为空。

    ① 方案数: ,枚举非空盒的数目,注意到盒子有区别,乘上一个排列系数即可。

    ② 既然允许盒子为空,且盒子间有区别,那么对于每个球有 m 种选择,每个球相互独立。有方案数:

4.算法实现

const int mod=1e9+7;//取模
LL s[N][N];//存放要求的Stirling数
void init(){memset(s,0,sizeof(s));s[1][1]=1;for(int i=2;i<=N-1;i++){for(int j=1;j<=i;j++){s[i][j]=s[i-1][j-1]+j*s[i-1][j];if(s[i][j]>=mod)s[i][j]%=mod;}}
}

5.扩展:S(n,m) 的奇偶性 

求 S(n,m) 的奇偶性实质就是求 S(n,m)%2

对于第二类斯特林数,首先有:S[i][j]=S[i−1][j−1]+j∗S[i−1][j]

那么在模 2 的情况下 ,有:

  • 当 j 为偶数:S[i][j] ≡(S[i−1][j−1]%2)
  • 当 j 为奇数:S[i][j] ≡((S[i−1][j−1]+S[i−1][j])%2)

于是,可以倒过来,即有:

  • 当 j 为偶数时:S[i][j] 会被加到 S[i+1][j+1] 和 S[i+1][j] 
  • 当 j 为奇数时:S[i][j] 会被加到 S[i+1][j+1]

于是,令 a=n−m,b=(m+1)/2,则答案就相当于把 a 个相同的球分成 b 组,每组个数可以为 0 的方案总数,即:C(b−1,a+b−1)

然后利用 C(n,m) 为奇数时有 n&m=n 的结论,进行判断即可

int calc(int n,int m){return (m&n)==n;
}
int main(){int n,m;scanf("%d%d",&n,&m);if(n==0&&m==0)//特判printf("1\n");else if(n==0||m==0||n<m)//特判printf("0\n");else{int a=n-m;int b=(m+1)/2;int res=calc(b-1,a+b-1);printf("%d\n",res);}return 0;
}

【两类斯特林数的关系】

两类斯特林数之间的递推式和实际含义很类似,他们之间存在一个互为转置的转化关系:

\sum_{k=0}^nS1(n,k)S2(k,m)=\sum_{k=0}^nS2(n,k)S1(k,m)

【例题】

  • Binary Stirling Numbers(POJ-1430)(第二类斯特林数):点击这里

这篇关于组合数学 —— 斯特林数(Stirling)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1070720

相关文章

hdu4869(逆元+求组合数)

//输入n,m,n表示翻牌的次数,m表示牌的数目,求经过n次操作后共有几种状态#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#includ

uva 10014 Simple calculations(数学推导)

直接按照题意来推导最后的结果就行了。 开始的时候只做到了第一个推导,第二次没有继续下去。 代码: #include<stdio.h>int main(){int T, n, i;double a, aa, sum, temp, ans;scanf("%d", &T);while(T--){scanf("%d", &n);scanf("%lf", &first);scanf

uva 10025 The ? 1 ? 2 ? ... ? n = k problem(数学)

题意是    ?  1  ?  2  ?  ...  ?  n = k 式子中给k,? 处可以填 + 也可以填 - ,问最小满足条件的n。 e.g k = 12  - 1 + 2 + 3 + 4 + 5 + 6 - 7 = 12 with n = 7。 先给证明,令 S(n) = 1 + 2 + 3 + 4 + 5 + .... + n 暴搜n,搜出当 S(n) >=

uva 11044 Searching for Nessy(小学数学)

题意是给出一个n*m的格子,求出里面有多少个不重合的九宫格。 (rows / 3) * (columns / 3) K.o 代码: #include <stdio.h>int main(){int ncase;scanf("%d", &ncase);while (ncase--){int rows, columns;scanf("%d%d", &rows, &col

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

Go组合

摘要 golang并非完全面向对象的程序语言,为了实现面向对象的继承这一神奇的功能,golang允许struct间使用匿名引入的方式实现对象属性方法的组合 组合使用注意项 使用匿名引入的方式来组合其他struct 默认优先调用外层方法 可以指定匿名struct以调用内层方法 代码 package mainimport ("fmt")type People struct{}type Pe

CSP-J基础之数学基础 初等数论 一篇搞懂(一)

文章目录 前言声明初等数论是什么初等数论历史1. **古代时期**2. **中世纪时期**3. **文艺复兴与近代**4. **现代时期** 整数的整除性约数什么样的整数除什么样的整数才能得到整数?条件:举例说明:一般化: 判断两个数能否被整除 因数与倍数质数与复合数使用开根号法判定质数哥德巴赫猜想最大公因数与辗转相除法计算最大公因数的常用方法:举几个例子:例子 1: 计算 12 和 18

2024年AMC10美国数学竞赛倒计时两个月:吃透1250道真题和知识点(持续)

根据通知,2024年AMC10美国数学竞赛的报名还有两周,正式比赛还有两个月就要开始了。计划参赛的孩子们要记好时间,认真备考,最后冲刺再提高成绩。 那么如何备考2024年AMC10美国数学竞赛呢?做真题,吃透真题和背后的知识点是备考AMC8、AMC10有效的方法之一。通过做真题,可以帮助孩子找到真实竞赛的感觉,而且更加贴近比赛的内容,可以通过真题查漏补缺,更有针对性的补齐知识的短板。

一些数学经验总结——关于将原一元二次函数增加一些限制条件后最优结果的对比(主要针对公平关切相关的建模)

1.没有分段的情况 原函数为一元二次凹函数(开口向下),如下: 因为要使得其存在正解,必须满足,那么。 上述函数的最优结果为:,。 对应的mathematica代码如下: Clear["Global`*"]f0[x_, a_, b_, c_, d_] := (a*x - b)*(d - c*x);(*(b c+a d)/(2 a c)*)Maximize[{f0[x, a, b,