斯特林数
斯特林数
一、第二类斯特林数
1、定义:表示将 \(n\) 个两两不同的元素,划分为 \(k\) 个互不区分的非空子集的方案数。
2、递推式记为:\(S(n,m)=S(n-1,m-1)+mS(n-1,m)\),边界是:\(S(n,0)=[n=0]\)。
3、组合数的意义:
-
前一项表示将新的元素单独放入一个子集。
-
后一项表示将新的元素放入一个已有的非空集合里面。
4、通项公式:
- \(S(n,m)=\sum_{i=0}^{m}\frac{(-1)^{m-i}i^n}{i!(m-i)!}\)。
\((1)\):第一种方案
-
代码 \(n\) 能为 \(1e6\),时间复杂度:\(O(nlog(n))\),但是要保证质数和其他数互质。
-
例题:牛客。
template<typename T>
struct SN2{
inline T qp(T a, T b, T p = 1e9 + 7) {
T res = 1;
a %= p;
for (; b; b >>= 1LL, a = a * a % p) {
if (b & 1) res = res * a % p;
}
return res;
}
inline T get_inv(T a, T p = 1e9 + 7) {
return qp(a, p - 2, p);
}
int N;
vector<T> fac, inv;
SN2() {}
SN2(int N_, T p = 1e9 + 7) : fac(N_ + 1), inv(N_ + 1) {
N = N_;
fac[0] = 1;
for (T i = 1; i <= N; i++) fac[i] = fac[i - 1] * i % p;
inv[N] = get_inv(fac[N], p);
for (T i = N - 1; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1) % p;
}
inline T C(T n, T m, T p = 1e9 + 7) {
if (n < m) {
return (T)0;
}
return fac[n] * inv[n - m] % p * inv[m] % p;
}
inline T S2(T n, T m, T p = 1e9 + 7) {
if (n < m) {
return (T)0;
}
T res = 0;
for (T i = 0; i <= m; i++) {
if ((m - i) & 1) res = (res - (qp(i, n, p) * inv[i] % p * inv[m - i] % p) + p) % p;
else res = (res + (qp(i, n, p) * inv[i] % p * inv[m - i] % p)) % p;
}
return res;
}
};
\((2)\):第二种方案
- 需要满足 \(n\) 为 \((2e3-1e4)\) 之间,查询的时间复杂度为 \(O(1)\),不需要满足模数与其他数互质。
template<typename T>
struct SN2{
inline T qp(T a, T b, T p = 1e9 + 7) {
T res = 1;
a %= p;
for (; b; b >>= 1LL, a = a * a % p) {
if (b & 1) res = res * a % p;
}
return res;
}
inline T get_inv(T a, T p = 1e9 + 7) {
return qp(a, p - 2, p);
}
static const int N = 2000;
T S2[N + 1][N + 1];
SN2(T p = 1e9 + 7) {
S2[0][0] = 1LL;
for (T i = 1; i <= N; i++) {
for (T j = 1; j <= i; j++) {
S2[i][j] = (S2[i - 1][j - 1] + (j * S2[i - 1][j] % p)) % p;
}
}
}
T S(T n, T m) {
return S2[n][m];
}
};
5、同一行第二类斯特林数的计算:更新中
6、同一列第二类斯特林数的计算:更新中
二、第一类斯特林数
1、定义:也叫斯特林轮换数,表示将 \(n\) 个两两不同的元素,划分为 \(k\) 个互不区分的非空轮换的方案数。
2、注意:一个轮换指的是首尾相连的环形排列。我们可以写出一个轮换 \([A,B,C,D]\),并且我么认为 \([A,B,C,D]=[B,C,D,A]=[C,D,A,B]=[D,A,B,C]\),即,两个可以通过旋转二互相得到的转化是等价的,但是我们不认为两个可以通过翻转而得到的转换是等价的,即 \([A,B,C,D] \ne [D,C,B,A]\)。
3、递推式为:\(S_{n}^{m}=S_{n-1}^{m-1}+(n-1)S_{n-1}^{m}\),边界是 \([S_{n}^{0}=[n=0]]\)。
4、组合数意义:
-
前一项表示将该元素放到一个单独的轮换里。
-
后一项表示将该元素放入任何一个现有的轮换里。
5、通项公式:暂无。
6、\(n\) 为 \((2e3-1e4)\) 之间,时间复杂度为 \(O(1)\)。
template<typename T>
struct SN1{
inline T qp(T a, T b, T p = 1e9 + 7) {
T res = 1;
a %= p;
for (; b; b >>= 1LL, a = a * a % p) {
if (b & 1) res = res * a % p;
}
return res;
}
inline T get_inv(T a, T p = 1e9 + 7) {
return qp(a, p - 2, p);
}
static const int N = 2000;
T S1[N + 1][N + 1];
SN1(T p = 1e9 + 7) {
S1[0][0] = 1;
for (T i = 1; i <= N; i++) {
for (T j = 1; j <= i; j++) {
S1[i][j] = (S1[i - 1][j - 1] + ((i - 1) * S1[i - 1][j] % p)) % p;
}
}
}
T S(T n, T m) {
return S1[n][m];
}
};
7、同一行第一类斯特林数的计算:更新中
8、同一列第一类斯特林数的计算:更新中

浙公网安备 33010602011771号