typedef int arr[maxn][maxn];
排列组合
排列与组合
从
n个不同的元素中,取
m个不重复的元素,按次序排列,称为从
n个中取
m个的排列。
Anm=(n−m)!n!
从
n个不同的元素中,取
m个不重复的元素,不考虑次序,称为从
n个中取
m个的组合。
Cnm=(n−m)!(m!)n!
组合数的性质:
Cnmi=0∑nCniCnm=Cnn−m=2n=Cn−1m+Cn−1m−1
解读:
- 性质1:从
n个数中选
m个数,等价于选出另外
n−m个数,这样这
m个数随之确定。
- 性质2:可以由二项式定理得到。
- 性质3:运用递推思想,讨论是否选第
n个数,若选则在前
n−1个数中选
m−1个数,否则在前
n−1个数中选
m个数。
根据
Cnm=Cn−1m+Cn−1m−1递推求组合数:
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−1in−i+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=0∑nCnkxn−kyk
真のLucas定理
求
Cnmmodp的值(
p为质数)。
Cnm≡CnmodpmmodpC⌊pn⌋⌊pm⌋(modp)
不想证明。
时间复杂度:
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定理
求
Cnmmodp的值(
p不一定为质数)。
首先将
p分解质因数:
p=p1k1p2k2p3k3…pqkq
然后得出一个同余方程组,用中国剩余定理求解。
⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧xxx≡Cnmmodp1k1(modp1k1)≡Cnmmodp2k2(modp2k2)⋮≡Cnmmodpqkq(modpqkq)
pqkq太大时,用Lucas算
Cnmmodpqkq会超时。怎么办?待补充。
Stirling数
第二类Stirling数表示把
n个元素划分成
m个非空集合的方案数。
Snm=Sn−1m−1+mSn−1m
**递推过程:**若前
n−1个元素已经分成了
m−1个集合,则第
n个元素自成一个集合,否则把第
n个元素放入
m个集合中的任意一个集合中。
void make_s2(arr s2,int n){
for(int i=1;i<=n;i++)s2[i][1]=1;
for(int i=1;i<=n;i++)for(int j=2;j<=i;j++)
s2[i][j]=s2[i-1][j-1]+j*s2[i-1][j];
}
第一类Stirling数表示把
n个元素划分成
m个非空循环排列集合的方案数。
snm=sn−1m−1+(n−1)sn−1m
**递推过程:**若前
n−1个元素已经分成了
m−1个集合,则第
n个元素自成一个集合,否则把第
n个元素放入前
n−1个元素中任意一个元素的左边。
void make_s1(arr s1,int n){
for(int i=1;i<=n;i++)s1[i][i]=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数表示把
n个元素划分成若干个非空集合的方案数。
Bn=k=1∑nSnk
Catalan数
Cn={1n+14n−2Cn−1n=1otherwise
Cn=n+1C2nn=C2nn−C2nn−1
问题描述:
-
n对括号有多少种有效配对方式?
-
P=A1×A2×A3×...×An,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?
- 有
n个整数
1,2,...,n和一个栈,进栈顺序为
1,2,...,n,每个数字都要出入一次栈,用
S表示数字入栈,
X表示数字出栈,那么合法的序列有多少个?
-
n个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?
(由
2n个
0和
2n个
1组成的序列中数字
1左侧
0的个数要大于
1的个数,问这样的序列由多少种?)
-
n个节点构成的二叉树,共有多少种不同情形?
- 在圆上选择
2n个点,将这些点成对连接起来使得所得到的
n条线段不相交的方法数?
- 将一个凸多边形划分成三角形总共有多少种方法?
- 用
n个长方形填充一个高度为
n的阶梯状图形的方法个数?
这些问题的答案都是Catalan数或与Catalan有关。
答案是多少呢?我忘了。