斯特林数

第一类斯特林数

含义

S ( i , j ) S(i,j) S(i,j) 表示 i i i 个不同元素,分成 j j j 个圆,排列的方案数
那么 S ( 0 , 0 ) = 1 , S ( i , 0 ) = 1 S(0,0)=1,S(i,0)=1 S(0,0)=1,S(i,0)=1
显然有
S ( i , j ) = S ( i − 1 , j − 1 ) + ( i − 1 ) S ( i − 1 , j ) S(i,j)=S(i-1,j-1)+(i-1)S(i-1,j) S(i,j)=S(i1,j1)+(i1)S(i1,j)

结论

∑ k = 0 n S ( n , k ) = n ! \sum_{k=0}^{n}S(n,k)=n! k=0nS(n,k)=n!

证明

一个排列对应一个置换
把这个置换中的上下对应位置连边,可以得到许多的环
由于排列和置换是一一对应的,所以我们要求排列的个数,就是求用n个元素组成环的方案数,所以我们枚举环的个数

它的生成函数

x n ‾ = x ( x + 1 ) ( x + 2 ) . . . ( x + n − 1 ) = ∑ k = 0 n S ( n , k ) x k x^{\overline{n}}=x(x+1)(x+2)...(x+n-1)=\sum_{k=0}^{n}S(n,k)x^k xn=x(x+1)(x+2)...(x+n1)=k=0nS(n,k)xk
x n ‾ = x ( x − 1 ) ( x − 2 ) . . . ( x − n + 1 ) = ∑ k = 0 n ( − 1 ) n − k S ( n , k ) x k x^{\underline{n}}=x(x-1)(x-2)...(x-n+1)=\sum_{k=0}^{n}(-1)^{n-k}S(n,k)x^k xn=x(x1)(x2)...(xn+1)=k=0n(1)nkS(n,k)xk

求法

可以直接 n l o g 2 n nlog^2n nlog2n 分治 F F T FFT FFT
或者还有一个 n l o g n nlogn nlogn 倍增的求法
F n ( x ) = ∏ i = 0 n − 1 ( x + i ) F_n(x)=\prod_{i=0}^{n-1}(x+i) Fn(x)=i=0n1(x+i)
那么 F 2 n ( x ) = F n ( x ) F n ( x + n ) F_{2n}(x)=F_n(x)F_n(x+n) F2n(x)=Fn(x)Fn(x+n)
考虑利用 F n ( x ) F_n(x) Fn(x) 推出 F n ( x + n ) F_n(x+n) Fn(x+n)
F n ( x ) = ∑ i = 0 n a i x i F_n(x)=\sum_{i=0}^{n}a_ix^i Fn(x)=i=0naixi
那么
F n ( x + n ) = ∑ i = 0 n a i ∑ j = 0 i ( i j ) x j n i − j = ∑ i = 0 n − 1 x i ∑ j = i n − 1 ( j i ) n j − i a j F_n(x+n)=\sum_{i=0}^{n}a_i\sum_{j=0}^{i}\binom{i}{j}x^jn^{i-j}=\sum_{i=0}^{n-1}x^i\sum_{j=i}^{n-1}\binom{j}{i}n^{j-i}a_j Fn(x+n)=i=0naij=0i(ji)xjnij=i=0n1xij=in1(ij)njiaj

∑ j = i n − 1 ( j i ) n j − i a j = 1 i ! ∑ j = i n − 1 j ! a j n j − i ( j − i ) ! \sum_{j=i}^{n-1}\binom{j}{i}n^{j-i}a_j=\frac{1}{i!}\sum_{j=i}^{n-1}j!a_j\frac{n^{j-i}}{(j-i)!} j=in1(ij)njiaj=i!1j=in1j!aj(ji)!nji
所以可以反转之后 F F T FFT FFT

CF960G

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn(1 << 18);
const int mod(998244353);

inline void Inc(int &x, int y) {
	x = x + y >= mod ? x + y - mod : x + y;
}

inline int Pow(ll x, int y) {
	register ll ret = 1;
	for (; y; y >>= 1, x = x * x % mod) if (y & 1) ret = ret * x % mod;
	return ret;
}

int f[maxn], w[2][maxn], a[maxn], b[maxn], c[maxn], l, r[maxn], len;

inline void Init(int n) {
	register int i, x, y;
	for (l = 0, len = 1; len < n; len <<= 1) ++l;
	for (i = 0; i < len; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
	x = Pow(3, (mod - 1) / len), y = Pow(x, mod - 2), w[0][0] = w[1][0] = 1;
	for (i = 1; i < len; ++i) w[0][i] = (ll)w[0][i - 1] * x % mod, w[1][i] = (ll)w[1][i - 1] * y % mod;
	for (i = 0; i < len; ++i) c[i] = a[i] = b[i] = 0;
}

inline void DFT(int *p, int opt) {
	register int i, j, t, k, x, y, wn;
	for (i = 0; i < len; ++i) if (r[i] < i) swap(p[i], p[r[i]]);
	for (i = 1; i < len; i <<= 1)
		for (t = i << 1, j = 0; j < len; j += t)
			for (k = 0; k < i; ++k) {
				wn = w[opt == -1][len / t * k];
				x = p[k + j], y = (ll)wn * p[i + j + k] % mod;
				p[k + j] = x + y >= mod ? x + y - mod : x + y;
				p[i + j + k] = x - y < 0 ? x - y + mod : x - y;
			}
	if (opt == -1) for (wn = Pow(len, mod - 2), i = 0; i < len; ++i) p[i] = (ll)p[i] * wn % mod;
}

int n, inv[maxn], fac[maxn], pw[maxn];

void Solve(int x) {
	if (x == 1) return f[1] = 1, void();
	register int i, cnt;
	if (x & 1) for (Solve(x - 1), i = x; i; --i) f[i] = ((ll)(x - 1) * f[i] + f[i - 1]) % mod;
	else {
		Solve(x >> 1), cnt = x >> 1, Init(x + 1);
		for (i = pw[0] = 1; i <= cnt; ++i) pw[i] = (ll)pw[i - 1] * cnt % mod;
		for (i = 0; i <= cnt; ++i) a[i] = (ll)fac[i] * f[i] % mod;
		for (i = 0; i <= cnt; ++i) b[i] = (ll)pw[i] * inv[i] % mod;
		reverse(b, b + cnt + 1), DFT(a, 1), DFT(b, 1);
		for (i = 0; i < len; ++i) a[i] = (ll)a[i] * b[i] % mod;
		for (DFT(a, -1), i = 0; i <= cnt; ++i) c[i] = (ll)a[cnt + i] * inv[i] % mod;
		for (DFT(f, 1), DFT(c, 1), i = 0; i < len; ++i) f[i] = (ll)f[i] * c[i] % mod;
		for (DFT(f, -1), i = x + 1; i < len; ++i) f[i] = 0;
	}
}

int main() {
	register int i, c = 1, a, b, m;
	scanf("%d%d%d", &n, &a, &b);
	if (a + b - 2 > n - 1 || !a || !b) return puts("0"), 0;
	if (n == 1) return puts(a == b && a == 1 ? "1" : "0");
	fac[0] = fac[1] = inv[0] = inv[1] = 1, m = a + b - 2;
	for (i = 2; i <= n; ++i) inv[i] = (ll)(mod - mod / i) * inv[mod % i] % mod;
	for (i = 1; i < a; ++i) c = (ll)c * (m - i + 1) % mod * inv[i] % mod;
	for (i = 2; i <= n; ++i) inv[i] = (ll)inv[i] * inv[i - 1] % mod, fac[i] = (ll)fac[i - 1] * i % mod;
	Solve(n - 1), c = (ll)c * f[a + b - 2] % mod, printf("%d\n", c);
    return 0;
}

第二类斯特林数

含义

n n n个有区别的球放在 m m m个相同的盒子内,要求盒子不为空的方案数
实际上也就是把数 n n n拆成 m m m个正整数和的方案数
记作 S ( n , m ) S(n, m) S(n,m)

性质

  1. S ( n , 0 ) = S ( 0 , n ) = 0 S(n, 0)=S(0, n)=0 S(n,0)=S(0,n)=0,其中 n ∈ N n \in N nN
  2. S ( n , k ) = 0 S(n, k)=0 S(n,k)=0,其中 k &gt; n &gt; = 1 k&gt;n&gt;=1 k>n>=1
  3. S ( n , n ) = S ( n , 1 ) = 1 S(n, n)=S(n, 1)=1 S(n,n)=S(n,1)=1,其中 n &gt; = 1 n&gt;=1 n>=1

等等…

求法

递推

S ( n , m ) = S ( n − 1 , m − 1 ) + S ( n − 1 , m ) ∗ m S(n, m) = S(n - 1, m - 1) + S(n - 1, m) * m S(n,m)=S(n1,m1)+S(n1,m)m,其中 n &gt; 1 , m &gt; = 1 n&gt;1,m&gt;=1 n>1m>=1
解释:新开一盒子或者在原有盒子中选一个

公式

S ( n , m ) = 1 m ! ∑ k = 0 m ( − 1 ) k C ( m , k ) ( m − k ) n S(n, m)=\frac{1}{m!}\sum_{k=0}^{m}(-1)^kC(m, k)(m-k)^n S(n,m)=m!1k=0m(1)kC(m,k)(mk)n

证明

先考虑 n n n个不同的球放在 m m m不同的盒子内没有无空盒限制的方案数
那么显然就是 m n m^n mn
考虑容斥原理
总的 − - 有大于等于一个空盒的方案 + + + 有大于等于两个个空盒的方案 − - 有大于等于三个空盒的方案…
写出来就是
S ( n , m ) = ∑ k = 0 m ( − 1 ) k C ( m , k ) ( m − k ) n S(n, m)=\sum_{k=0}^{m}(-1)^kC(m, k)(m-k)^n S(n,m)=k=0m(1)kC(m,k)(mk)n
因为我们认为盒子有区别
C ( m , k ) C(m, k) C(m,k)就是把那 k k k个空盒子选出来
其他的随便放

现在求出了 n n n个不同的球放在 m m m不同的盒子内有无空盒限制的方案数
然而要求的是盒子无区别的
还要除以一个 1 m ! \frac{1}{m!} m!1
就得到了那个公式

其他的一些东西

S ( n , m ) = 1 m ! ∑ k = 0 m ( − 1 ) k C ( m , k ) ( m − k ) n S(n, m)=\frac{1}{m!}\sum_{k=0}^{m}(-1)^kC(m, k)(m-k)^n S(n,m)=m!1k=0m(1)kC(m,k)(mk)n
假设 n n n固定,那么预处理出 C ( m , k ) C(m, k) C(m,k)就可以直接多项式卷积求出来所有的 S ( n , m ) S(n,m) S(n,m)

考虑换一种形式
S ( n , m ) = 1 m ! ∑ k = 0 m ( − 1 ) k C ( m , k ) ( m − k ) n S(n, m)=\frac{1}{m!}\sum_{k=0}^{m}(-1)^kC(m, k)(m-k)^n S(n,m)=m!1k=0m(1)kC(m,k)(mk)n
= 1 m ! ∑ k = 0 m ( − 1 ) k m ! k ! ( m − k ) ! ( m − k ) n =\frac{1}{m!}\sum_{k=0}^{m}(-1)^k\frac{m!}{k!(m-k)!}(m-k)^n =m!1k=0m(1)kk!(mk)!m!(mk)n
= ∑ k = 0 m ( − 1 ) k k ! ( m − k ) n ( m − k ) ! =\sum_{k=0}^{m}\frac{(-1)^k}{k!}\frac{(m-k)^n}{(m-k)!} =k=0mk!(1)k(mk)!(mk)n

这样就可以不用预处理组合数直接 F F T FFT FFT求了

推论

  • 因为 S ( m , m ) = 1 S(m, m)=1 S(m,m)=1,所以
    m ! = ∑ k = 0 m ( − 1 ) k C ( m , k ) ( m − k ) m m!=\sum_{k=0}^{m}(-1)^kC(m, k)(m-k)^m m!=k=0m(1)kC(m,k)(mk)m
  • m n m^n mn类似表示,即用第二类斯特林数表示 n n n个不同的球放在 m m m不同的盒子内没有无空盒限制的方案数
    这次枚举不是空的的盒子
    m n = ∑ k = 0 m S ( n , k ) k ! C ( m , k ) m^n=\sum_{k=0}^{m}S(n, k)k!C(m, k) mn=k=0mS(n,k)k!C(m,k)

两个之间的关系

反转公式
{ ∑ k = m n ( − 1 ) n − k [ n k ] { k m } = [ n = m ] ∑ k = m n ( − 1 ) n − k [ k m ] { n k } = [ n = m ] \begin{cases}\sum_{k=m}^n(-1)^{n-k}\begin{bmatrix}n\\k\end{bmatrix}\begin{Bmatrix}k\\m\end{Bmatrix}=[n=m]\\\sum_{k=m}^n(-1)^{n-k}\begin{bmatrix}k\\m\end{bmatrix}\begin{Bmatrix}n\\k\end{Bmatrix}=[n=m]\end{cases} k=mn(1)nk[nk]{km}=[n=m]k=mn(1)nk[km]{nk}=[n=m]

第一类Stirling数幂与下降幂的关系
x k ‾ = ∑ i = 0 k ( − 1 ) k − i [ k i ] x i x^{\underline k}=\sum_{i=0}^k(-1)^{k-i}\begin{bmatrix} k\\i \end{bmatrix}x^i xk=i=0k(1)ki[ki]xi

第二类Stirling数幂与下降幂的关系
x k = ∑ i = 0 k { k i } x i ‾ x^{k}=\sum_{i=0}^k\begin{Bmatrix} k\\i \end{Bmatrix}x^{\underline i} xk=i=0k{ki}xi

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值