【组合数学】排列组合与各种计数数列

本文深入探讨了排列组合的基本概念及其性质,介绍了Catalan数、Stirling数及Bell数等特殊数列的定义与应用,通过实例解析了它们在解决实际问题中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

typedef int arr[maxn][maxn];

排列组合

排列与组合

nnn个不同的元素中,取mmm个不重复的元素,按次序排列,称为从nnn个中取mmm个的排列
Anm=n!(n−m)!A_n^m=\frac{n!}{(n-m)!}Anm=(nm)!n!

nnn个不同的元素中,取mmm个不重复的元素,不考虑次序,称为从nnn个中取mmm个的组合
Cnm=n!(n−m)!(m!)C_n^m=\frac{n!}{(n-m)!(m!)}Cnm=(nm)!(m!)n!

组合数的性质:
Cnm=Cnn−m∑i=0nCni=2nCnm=Cn−1m+Cn−1m−1\begin{aligned} C_n^m&=C_n^{n-m}\\ \sum_{i=0}^nC_n^i&=2^n\\ C_n^m&=C_{n-1}^m+C_{n-1}^{m-1} \end{aligned}Cnmi=0nCniCnm=Cnnm=2n=Cn1m+Cn1m1

解读:

  • 性质1:从nnn个数中选mmm个数,等价于选出另外n−mn-mnm个数,这样这mmm个数随之确定。
  • 性质2:可以由二项式定理得到。
  • 性质3:运用递推思想,讨论是否选第nnn个数,若选则在前n−1n-1n1个数中选m−1m-1m1个数,否则在前n−1n-1n1个数中选mmm个数。

根据Cnm=Cn−1m+Cn−1m−1C_n^m=C_{n-1}^m+C_{n-1}^{m-1}Cnm=Cn1m+Cn1m1递推求组合数:

void make_C(arr C,int n){
  for(int i=0;i<=n;i++)C[i][0]=1;
  for(int i=1;i<=n;i++)
    for(int j=1;j<=i;j++)
      C[i][j]=C[i-1][j]+C[i-1][j-1];
}

根据定义式推出Cni=Cni−1n−i+1iC_n^i=C_n^{i-1}\frac{n-i+1}iCni=Cni1ini+1求出某一行组合数:

void make_Cn(int*C,int n){
  C[0]=1;
  for(int i=1;i<=n;i++)C[i]=C[i-1]*(n-i+1)/i;
}

二项式定理

(x+y)n=∑k=0nCnkxn−kyk(x+y)^n=\sum_{k=0}^nC_n^kx^{n-k}y^k(x+y)n=k=0nCnkxnkyk

真のLucas定理

Cnmmod  pC_n^m\mod pCnmmodp的值(ppp为质数)。
Cnm≡Cnmod  pmmod  pC⌊np⌋⌊mp⌋(modp)C_n^m\equiv C_{n\mod p}^{m\mod p}C_{\lfloor\frac np\rfloor}^{\lfloor\frac mp\rfloor}\pmod pCnmCnmodpmmodpCpnpm(modp)

不想证明。
时间复杂度:O(plog⁡pm)O(p\log_pm)O(plogpm)

int C(int a,int b,int p){
  if(a<b)return 0;
  if(a==b)return 1;
  if(b>a-b)b=a-b;
  int A=1,B=1;
  for(int i=0;i<b;i++)A=A*(a-i)%p,B=B*(b-i)%p;
  return A*Pow(B,p-2,p)%p;
}
int Lucas(int n,int m,int p){
  return m?C(n%p,m%p,p)*Lucas(n/p,m/p,p)%p:1;
}

扩展Lucas定理

Cnmmod  pC_n^m\mod pCnmmodp的值(ppp不一定为质数)。
首先将ppp分解质因数:p=p1k1p2k2p3k3…pqkqp=p_1^{k_1}p_2^{k_2}p_3^{k_3}\dots p_q^{k_q}p=p1k1p2k2p3k3pqkq
然后得出一个同余方程组,用中国剩余定理求解。
{x≡Cnmmod  p1k1(modp1k1)x≡Cnmmod  p2k2(modp2k2)⋮x≡Cnmmod  pqkq(modpqkq)\begin{cases} x&\equiv C_n^m\mod p_1^{k_1}\pmod{p_1^{k_1}}\\ x&\equiv C_n^m\mod p_2^{k_2}\pmod{p_2^{k_2}}\\ &\vdots\\ x&\equiv C_n^m\mod p_q^{k_q}\pmod{p_q^{k_q}} \end{cases}xxxCnmmodp1k1(modp1k1)Cnmmodp2k2(modp2k2)Cnmmodpqkq(modpqkq)

ki>1k_i>1ki>1时,Cnmmod  pikiC_n^m\mod p_i^{k_i}Cnmmodpiki怎么计算?待补充。

Stirling数

第二类Stirling数表示把nnn个元素划分成mmm个非空集合的方案数。
Snm=Sn−1m−1+mSn−1mS_n^m=S_{n-1}^{m-1}+mS_{n-1}^mSnm=Sn1m1+mSn1m

递推过程: 若前n−1n-1n1个元素已经分成了m−1m-1m1个集合,则第nnn个元素自成一个集合,否则把第nnn个元素放入mmm个集合中的任意一个集合中。

void make_s2(arr s2,int n){
  s2[0][0]=1;
  for(int i=1;i<=n;i++)
    for(int j=1;j<=i;j++)
      s2[i][j]=s2[i-1][j-1]+j*s2[i-1][j];
}

第一类Stirling数表示把nnn个元素划分成mmm个非空循环排列集合的方案数。
snm=sn−1m−1+(n−1)sn−1ms_n^m=s_{n-1}^{m-1}+(n-1)s_{n-1}^msnm=sn1m1+(n1)sn1m

递推过程: 若前n−1n-1n1个元素已经分成了m−1m-1m1个集合,则第nnn个元素自成一个集合,否则把第nnn个元素放入前n−1n-1n1个元素中任意一个元素的左边。

void make_s1(arr s1,int n){
  s1[0][0]=1;
  for(int i=1;i<=n;i++)
    for(int j=1;j<=i;j++)
      s1[i][j]=s1[i-1][j-1]+(i-1)*s1[i-1][j];
}

Bell数

Bell数表示把nnn个元素划分成若干个非空集合的方案数。
Bn=∑k=1nSnkB_n=\sum_{k=1}^nS_n^kBn=k=1nSnk

Catalan数

Cn={1n=14n−2n+1Cn−1otherwiseC_n=\begin{cases} 1&n=1\\ \frac{4n-2}{n+1}C_{n-1}&\text{otherwise} \end{cases}Cn={1n+14n2Cn1n=1otherwise

Cn=C2nnn+1=C2nn−C2nn−1C_n=\frac{C_{2n}^n}{n+1}=C_{2n}^n-C_{2n}^{n-1}Cn=n+1C2nn=C2nnC2nn1

问题描述:

  • nnn对括号有多少种有效配对方式?
  • P=A1×A2×A3×...×AnP=A_1\times{A_2}\times{A_3}\times...\times{A_n}P=A1×A2×A3×...×An,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?
  • nnn个整数1,2,...,n1,2,...,n1,2,...,n和一个栈,进栈顺序为1,2,...,n1,2,...,n1,2,...,n,每个数字都要出入一次栈,用SSS表示数字入栈,XXX表示数字出栈,那么合法的序列有多少个?
  • nnn个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?
    (由n2\frac n22n000n2\frac n22n111组成的序列中数字111左侧000的个数要大于111的个数,问这样的序列由多少种?)
  • nnn个节点构成的二叉树,共有多少种不同情形?
  • 在圆上选择2n2n2n个点,将这些点成对连接起来使得所得到的nnn条线段不相交的方法数?
  • 将一个凸多边形划分成三角形总共有多少种方法?
  • nnn个长方形填充一个高度为nnn的阶梯状图形的方法个数?

这些问题的答案都是Catalan数或与Catalan有关。
答案是多少呢?我忘了。

...
void make_catalan(unsigned_Int*h,int n){
  h[1]=1;
  for(int i=2;i<=n;i++)h[i]=h[i-1]*(4*i-2)/(i+1);
}

其中unsigned_Int为高精度非负整数类型。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值