组合数学学习笔记
组合数学学习笔记
——by sunzz3183
组合
定义
从 \(n\) 个元素中选 \(m\) 个元素的所有情况数(无顺序),记为
公式
代码
- 直接求
inline int ksm(int a,int b){int t=1;for(;b;b>>=1,a=a*a%p)if(b&1)t=t*a%p;return t%p;}
inline int C(int n,int m){
if(n<m)return 0;
if(m>n-m)m=n-m;
int a=1,b=1;
for(int i=1;i<=m;i++)
a=a*(n-i+1)%p,b=b*i%p;
return a*ksm(b,p-2)%p;
}
- 预处理阶乘求
int fac[N],inv[N];
inline int ksm(int a,int b){int t=1;for(;b;b>>=1,a=a*a%mod)if(b&1)t=t*a%mod;return t%mod;}
void init(int n){
fac[0]=inv[0]=1;
for(int i=1;i<=n;i++)
fac[i]=fac[i-1]*i%mod;
inv[n]=ksm(fac[n],mod-2);
for(int i=n;i>=1;i--)
inv[i-1]=inv[i]*i%mod;
}
inline int C(int n,int m){
if(n<m)return 0;
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
拓展
因为
所以
万用表
可以找到大部分组合数的规律
其中第 \(n\) 行 \(m\) 列为 \(C_{n+m}^m\) 或 \(C_{n+m}^n\)
排列
从 \(n\) 个元素中选 \(m\) 个元素的排列的所有情况数(有顺序),记为
公式
Lucas定理
代码
inline int Lucas(int n,int m){return m?Lucas(n/p,m/p)*C(n%p,m%p)%p:1;}
卡特兰(Catalan)数
意义
从 \((0,0)\) 不越过直线 \(y=x\) ,走到 \((n,n)\) 的方案个数。
式子
设 \(h(n)\) 为卡特兰数的第 \(n\) 项。
令 \(h(0)=1,h(1)=1\),卡特兰数满足递推式
另类递推式:
非递推:
拓展
在求一些走到 \((n,m)\) 的时候
多重集组合数
描述
给定 \(n(1\leq n \leq 20)\) 个数,每个数最多选 \(a_i(1\leq a_i \leq 10^{12})\),一共选 \(m(1\leq m \leq 10^{14})\) 个数,问方案数。
分析
显然,当 \(a_i\geq m\) 时,答案为
那么如果不满足这种情况呢?
设第 \(i\) 个数字为 \(b_i\),此题可以转化为,从可重集
选 \(m\) 个数的方案数。
根据容斥可得:
实现时通过枚举二进制 \(0\sim 2^n-1\) 来加减。
球盒问题
球不同,盒子不同,能有空可以重复放
球不同,盒子不同,不能有空可以重复放
考虑容斥
球不同,盒子同,不能有空可以重复放
第二类斯特林数
递推式:
球不同,盒子同,能有空可以重复放
枚举几个空
第二类斯特林数前缀和
球同,盒子不同,能/不能有空可以重复放
隔板法
能:
不能:
球同,盒子同,能为空可以重复放
考虑 \(DP\)。
设 \(f_{n,m}\) 为 \(n\) 个球放进 \(m\) 个盒子的方案数。
则
解释:\(f_{n,m-1}\) 为新加一个为空的格子,\(f_{n-m,m}\) 为每个格子都加一个球。
球同,盒子同,不能为空可以重复放
上一个问题的 $ f_{n-m,m} $。
由上一题得出差分式子 $ f_{n,m}-f_{n,m-1} $。
小思考
盒子不同容斥,盒子同不容斥
由前面的全部式子可以看出,相同是不同的前缀和,而前缀和反演是差分,所以不容斥(有一点点吧)。