Chgtaxihe's blog Chgtaxihe's blog
首页
练习
算法学习
读书笔记
小玩意

Chgtaxihe

首页
练习
算法学习
读书笔记
小玩意
  • 数论

    • 一些小问题
    • 二次剩余学习笔记
    • 卡特兰数学习笔记
    • 同余最短路学习笔记
    • 康托展开学习笔记
    • 快速傅里叶变换学习笔记
    • 拉格朗日插值学习笔记
    • 拓展欧几里得学习笔记
    • 斐波那契数列学习笔记
    • 斯特林数笔记
      • 例题 HDU 3625
      • 例题 HDU 4372
    • 本原勾股数组学习笔记
    • 模运算学习笔记
    • 欧拉函数
    • 类欧几里得学习笔记
    • 素性检测与大数分解
    • 素数计数问题
    • 组合数问题
    • 高斯整数学习笔记
  • 动态规划

  • 暴力

  • 图论

  • 数据结构

  • 字符串

  • 几何

  • 博弈论

  • 其他

斯特林数笔记

# 第二类斯特林数

把nnn个不同的球放到rrr个相同的盒子里,假设没有空盒,则放球方案数记做S(n,r)S(n, r)S(n,r)或SnrS_n^rSnr​,称为第二类 Stirling 数。

显然Sn1=1,Sn0=0,Snn=1S_n^1=1,S_n^0=0,S_n^n=1Sn1​=1,Sn0​=0,Snn​=1

# 递推形式

考虑最后一个球,如果把它单独放一个盒子,则有S(n−1,r−1)S(n-1,r-1)S(n−1,r−1)种方案,如果把它同前面的某一个球放到同一个盒子,有rS(n−1,r)rS(n-1,r)rS(n−1,r)种方案

S(n,r)=rS(n−1,r)+S(n−1,r−1)(n>r≥1)S(n,r)=rS(n-1, r) + S(n-1,r-1)\ (n>r\ge 1)S(n,r)=rS(n−1,r)+S(n−1,r−1)(n>r≥1)

# 其他公式

S(n,m)=1m!∑k=0m(−1)kCmk(m−k)n\large S(n,m)=\frac{1}{m!}\sum_{k=0}^m(-1)^kC_m^k(m-k)^nS(n,m)=m!1​∑k=0m​(−1)kCmk​(m−k)n,其中CmkC_m^kCmk​为组合数C(m,k)C(m, k)C(m,k)

容斥原理可得上式,由于盒子相同,最后要除以m!m!m!

nk=∑i=0ki!S(k,i)C(n,i)\large n^k=\sum_{i=0}^k i!S(k,i)C(n,i)nk=∑i=0k​i!S(k,i)C(n,i)

左边就是k个球可以任意放置在n个盒子里。 右边就是枚举非空盒子的数量i,那么把k个球放在i个盒子(盒子不同,需要乘上一个i!)里面再乘上选出i个非空盒子的方案数。

# 第一类斯特林数

s(n,r)s(n,r)s(n,r)是把nnn个不同的球排成rrr个非空循环排列的方法数

设多项式x(x−1)(x−2)...(x−n+1)x(x-1)(x-2)...(x-n+1)x(x−1)(x−2)...(x−n+1),展开式型如snxn−sn−1xn−1+sn−2xn−2−...s_nx^n-s_{n-1}x^{n-1}+s_{n-2}x^{n-2}-...sn​xn−sn−1​xn−1+sn−2​xn−2−...

不考虑各项系数符号,xrx^rxr的系数的绝对值记作为s(n,r)s(n,r)s(n,r),称为第一类斯特林数。

# 递推形式

s(n,r)=(n−1)s(n−1,r)+s(n−1,r−1)(n>r≥1)s(n,r)=(n-1)s(n-1,r)+s(n-1,r-1)\ (n>r\ge 1)s(n,r)=(n−1)s(n−1,r)+s(n−1,r−1)(n>r≥1)

考虑最后一个球,若它单独放一个圈,有s(n−1,r−1)s(n-1,r-1)s(n−1,r−1)种放法;若是放在前面的某一个球的左边,则有(n−1)s(n−1,r)(n-1)s(n-1,r)(n−1)s(n−1,r)种放法。

s(0,0)=1,s(n,0)=0,s(n,n)=1s(0,0)=1, s(n,0)=0, s(n,n)=1s(0,0)=1,s(n,0)=0,s(n,n)=1

# 例题 HDU 3625

有 n 个房间,编号为 1 到 n,每个房间对应有一把钥匙。现在把这 n 把钥匙随机地放在这 n 个房间中,并把门锁上。现在要将这 n 个房间的门都打开,你有 k 次把门炸开的机会,不过 1 号房间的门过于坚固炸不开。问能够成功打开所有门的概率。


也就是说,1号房间的钥匙不能在1号房内,且nnn个房间组成的环数不大于kkk

当nnn个房间组成iii个环,有合法方案数ansi=s(n,i)−s(n−1,i−1)ans_i=s(n,i)-s(n-1,i-1)ansi​=s(n,i)−s(n−1,i−1),s(n,i)s(n,i)s(n,i)为nnn个数组成iii个环的方案数,s(n−1,i−1)s(n-1,i-1)s(n−1,i−1)为2→n2\to n2→n组成了i−1i-1i−1个环(即111号房自己成环)的方案数。

答案为∑i=1kansin!\large\frac{\sum_{i=1}^kans_i}{n!}n!∑i=1k​ansi​​

AC代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

ll stirling[30][30], fac[30];
void solve(){
    ll n, k;
    cin >> n >> k;
    double ans = 0;
    for(int i=1; i<=k; i++){
        ans = ans + (1.0 * (stirling[n][i] - stirling[n-1][i-1]) / fac[n]);
    }
    cout << fixed << setprecision(4) << ans << endl;
}

void init(){
    stirling[0][0] = fac[0] = 1;
    for(int i=1; i<=20; i++){
        fac[i] = fac[i-1] * i;
        for(int j=1; j<=i; j++){
            stirling[i][j] = (i-1) * stirling[i-1][j] + stirling[i-1][j-1];
        }
    }
}

signed main(){
    init();
    int t; cin >> t;
    while(t--) solve();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 例题 HDU 4372

不知道为什么用逆元求组合数会WA。

BTW,垃圾HDU,OOM报的是WA。

#include <bits/stdc++.h>
#define ll long long

using namespace std;

const ll mod = 1e9 + 7;
const int maxn = 2020;
ll stirling[maxn][maxn], comb[maxn][maxn];

void solve(){
    ll n, f, b;
    cin >> n >> f >> b;
    ll ans = comb[f+b-2][f-1] * stirling[n-1][f+b-2] % mod;
    cout << ans << '\n';
}

void init(){
    stirling[0][0] = comb[0][0] = 1;
    for(int i=1; i<maxn; i++){
        comb[i][0] = 1;
        for(int j=1; j<=i; j++){
            comb[i][j] = (comb[i-1][j] + comb[i-1][j-1]) % mod;
            stirling[i][j] = ((i-1) * stirling[i-1][j] % mod + stirling[i-1][j-1]) % mod;
        }
    }
}

signed main(){
    init();
    int t; cin >> t;
    while(t--) solve();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
上次更新: 2021/02/24, 03:37:30
斐波那契数列学习笔记
本原勾股数组学习笔记

← 斐波那契数列学习笔记 本原勾股数组学习笔记→

最近更新
01
深入理解Java虚拟机
03-04
02
DNS工作原理
02-27
03
改用VuePress啦
02-23
更多文章>
Theme by Vdoing | Copyright © 2019-2021
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式