贝尔数
怎么感觉这么简单的东西被我写得这么搞基
前置知识:
- 第二类斯特林数(Stirling Number)\(\begin{Bmatrix}n\\k\end{Bmatrix}\) 或 \(S(n,k)\) 表示将 \(n\) 个元素划分为 \(k\) 个互不区分的非空子集的方案数。
- 递推式:\(S(n,k) = S(n-1,k-1) + k \times S(n-1,k)\),其中 \(S(n,0)=[n=0]\)。
 
 
贝尔数 \(B_n\) 表示 \(n\) 个元素被划分为若干个互不区分的非空子集的方案数(注意 \(B_0 = 1\))。
显然 \(B_n = \sum\limits_{k=0}^{n}{S(n,k)}\) 就是求同一行第二类斯特林数的和,luogu - P5395 第二类斯特林数·行。
还有递推式 \(B_{n+1} = \sum\limits_{k=0}^{n}{\dbinom{n}{k}B_k}\)(考虑 \(a_{n+1}\) 和哪些元素一个集合)
打表代码
#include <bits/stdc++.h>
using namespace std;
using LL = __int128_t;
const LL mod = LL(1e18) + 3;
void write(LL x){ if(x > 9) write(x / 10); putchar(x % 10 + '0'); }
LL qpow(LL A, LL B){
  LL ret = 1;
  while(B > 0){
    if(B & 1) ret = ret * A % mod;
    A = A * A % mod, B >>= 1;
  }
  return ret;
}
LL fac[1003], ifac[1003], B[1003];
LL C(int A, int B){ return fac[B] * ifac[A] % mod * ifac[B - A] % mod; }
int main(){
  ios::sync_with_stdio(0), cin.tie(0);
  fac[0] = ifac[0] = 1;
  for(int i = 1; i <= 1000; i++) fac[i] = fac[i - 1] * i % mod, ifac[i] = qpow(fac[i], mod - 2);
  B[0] = 1;
  for(int n = 1; n <= 15; n++){
    B[n] = 0;
    for(int k = 0; k <= n - 1; k++) B[n] = (B[n] + C(k, n - 1) * B[k]) % mod;
    write(n), putchar(' '), write(B[n]), putchar('\n');
  }
  return 0;
}
表:
1:  1
2:  2
3:  5
4:  15
5:  52
6:  203
7:  877
8:  4,140
9:  21,147
10: 115,975
11: 678,570
12: 4,213,597
13: 27,644,437
14: 190,899,322
15: 1,382,958,545
这玩意就用来分析时间复杂度的,在 代码源 2025 CSP-S 模拟赛 Day13 - D题 蝴蝶图 & QOJ - #913. 蝴蝶图 中用到了(\(B_{11} = 678,570\))。
如何枚举划分为若干个互不区分的非空子集的方案
前置知识:子集遍历
函数 dfs(int s) 表示 \(s\) 还没被选。考虑给每个集合内的点,标记为集合中最小的位置。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int n, rt[20], cnt = 0;
void dfs(int s){
  if(!s){
    cnt++;
    for(int i = 1; i <= n; i++){
      cout << rt[i] << " ";
    }
    cout << "\n";
    return;
  }
  int lowbit = (s & (-s)), p = 0;
  while((1 << p) != lowbit) p++;
  p++, rt[p] = p;
  s ^= lowbit;
  int st = s;
  while(st){
    for(int i = 1; i <= n; i++) if((st >> (i-1)) & 1) rt[i] = p;
    dfs(s ^ st);
    st = (st - 1) & s; 
  }
  dfs(s);
}
int main(){
  ios::sync_with_stdio(0), cin.tie(0);
  n = 5, dfs((1 << 5) - 1);
  cout << cnt << "\n";
  return 0;
}
                    
                
                
            
        
浙公网安备 33010602011771号