先简单介绍一下stirling数:
Stirling数概念
Stirling数出现在许多组合枚举问题中。对第一类Stirling数 ,也可记为
。表示将 n 个不同元素构成m个圆排列的数目。同时还分为无符号第一类Stirling数
和带符号第一类Stirling数
。
第二类Stirling数 ,同时可记为
[与第一类的表示有大小写的区别]。其表示将n个不同的元素分成m个集合的方案数。
在介绍第一类stirling数前,简单说一下 圆排列的定义:从n个不同元素中不重复取出m(1<=m<=n)个元素在一个圆周上,叫做这n个不同元素的圆排列。
第一类Stirling数
定义
第一类Stirling数表示表示将 n 个不同元素构成m个圆排列的数目。又根据正负性分为无符号第一类Stirling数 和带符号第一类Stirling数
。有无符号Stirling数分别表现为其升阶函数和降阶函数的各项系数[类似于二项式系数],形式如下:
对于有无符号Stirling数之间的关系有 。组合数学中的第一类Stirling数一般指无符号的第一类Stirling数。意思是n个不同元素构成m个圆排列的方案数。
递推式
无符号第一类Stirling数的递推式可以从其定义来推导:
考虑其定义如果要将n+1元素构成m个圆排列,考虑第n+1个元素:
(1)如果n个元素构成了m-1个圆排列,那么第n+1个元素独自构成一个圆排列。方案数:
(2)如果n个元素构成了m个圆排列,将第n+1个元素插入到任意元素的左边。方案数:
综合两种情况得:
而有符号的第一类Stirling数可以从其表示的降阶函数归纳证明(简单写如下):
依次把 在左右两边的系数提取出来得:
无符号Stirling数有如下性质:
①
②
③
④
⑤
⑥
⑦
⑧ 证明可令升阶函数中的x=1,比较两边系数。
有符号stirling性质类似:
①
⑧ ,注意
。证明可令降阶函数中的x=1,比较两边系数。
应用举例
第一类Stirling除了表示可以表示升阶函数和降阶函数的系数之外还可以应用到一些实际问题上。例如很经典的解锁仓库问题。
问题说明如下:有n个仓库,每个仓库有两把钥匙,共2n把钥匙。同时又有n位官员。问如何放置钥匙使得所有官员都能够打开所有仓库?(只考虑钥匙怎么放到仓库中,而不考虑官员拿哪把钥匙。)那如果官员分成m个不同的部,部中的官员数量和管理的仓库数量一致。那么有多少方案使得,同部的所有官员可以打开所有本部管理的仓库,而无法打开其他部管理的仓库?(同样只考虑钥匙的放置。)
第一问很经典,就是打开将钥匙放入仓库构成一个环:1号仓库放2号钥匙,2号仓库放3号钥匙……n号仓库放1号钥匙。这种情况相当于钥匙和仓库编号构成一个圆排列方案数是 种。
而第二问就对应的将n个元素分成m个圆排列,方案数就是第一类无符号Stirling数 。如要要考虑官员的情况,只需再乘上 即可。
第二类Stirling数
定义
第二类Stirling数实际上是集合的一个拆分,表示将n个不同的元素拆分成m个集合的方案数,记为 或者
。和第一类Stirling数不同的是,集合内是不考虑次序的,而圆排列是有序的。常常用于解决组合数学中几类放球模型。描述为:将n个不同的球放入m个无差别的盒子中,要求盒子非空,有几种方案?
第二类Stirling数要求盒子是无区别的,所以可以得到其方案数公式:
递推式
第二类Stirling数的推导和第一类Stirling数类似,可以从定义出发考虑第n+1个元素的情况,假设要把n+1个元素分成m个集合则分析如下:
(1)如果n个元素构成了m-1个集合,那么第n+1个元素单独构成一个集合。方案数 。
(2)如果n个元素已经构成了m个集合,将第n+1个元素插入到任意一个集合。方案数 m*S(n,m) 。
综合两种情况得:
性质
①
②
③
④
⑤
⑥
⑦
⑧
⑨ , 是贝尔数(给出了集合划分的数目,是组合数学中的一组整数数列)。
推论
(1) 若n小于m
(2)因为S(m,m)=1,所以有
应用举例(很重要)
第二类Stirling数主要是用于解决组合数学中的几类放球模型。主要是针对于球之前有区别的放球模型:
(1)n个不同的球,放入m个无区别的盒子,不允许盒子为空。
方案数: 。这个跟第二类Stirling数的定义一致。
(2)n个不同的球,放入m个有区别的盒子,不允许盒子为空。
方案数: 。因盒子有区别,乘上盒子的排列即可。
(3)n个不同的球,放入m个无区别的盒子,允许盒子为空。
方案数: 。枚举非空盒的数目便可。
(4)n个不同的球,放入m个有区别的盒子,允许盒子为空。
①方案数: 。同样可以枚举非空盒的数目,注意到盒子有区别,乘上一个排列系数。
②既然允许盒子为空,且盒子间有区别,那么对于每个球有m中选择,每个球相互独立。有方案数: 。
上述式子可以应用于第二类Stirling数通项的求解。
通项公式:
这个通项公式有多种方法推导。常用的有容斥原理,母函数和等式求解等。
两类Stirling数之间的关系
两类Stirling数之间的递推式和实际含义很类似,事实上他们之间存在一个互为转置的转化关系:
类似于矩阵的对称转置关系。
题目:
Description
The new season has begun, you have n competitions and m well prepared decks during the new season. Each competition you could use any deck you want, but each of the decks must be used at least once. Now you wonder how many ways are there to plan the season — to decide for each competition which deck you are going to used. The number can be very huge, mod it with 10^9 + 7.
Input
The input file contains several test cases, one line for each case contains two integer numbers n and m (1 ≤ m ≤ n ≤ 100).
Output
One line for each case, output one number — the number of ways.
Sample Input
3 2
100 25
Sample Output
6
354076161
**【题意】:**新赛季开始,有n场比赛,m个场地,问你有多少种办法来规划。
**【思路】:**就是第二类stirling数中几种常见模型的第二种(因为每个场地都是不同的)
【代码】:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
using namespace std;
const int N=200;
const long long M=1e9+7;
long long dp[N][N];
int main()
{
ios::sync_with_stdio(false);
int n,m;
memset(dp,0,sizeof(dp));
dp[1][1]=1;
for(int i=2;i<=101;i++)
for(int j=1;j<=i;j++)
dp[i][j]=(dp[i-1][j-1]+j*dp[i-1][j])%M;
while(cin>>n>>m)
{
long long ans=1;
for(int i=1;i<=m;i++)
ans=(ans%M*i%M)%M;
cout<<(ans*dp[n][m])%M<<endl;
}
return 0;
}