组合数模板
Cnm=Cn−1m−1+Cnm−1=n!m!∗(n−m)!C_n^m=C_{n-1}^{m - 1}+C_n^{m - 1}=\frac{n!}{m!*(n-m)!}Cnm=Cn−1m−1+Cnm−1=m!∗(n−m)!n!
Anm=n(n−1)(n−2)...(n−m+1)=n!(n−m)!A_n^m=n(n-1)(n-2)...(n-m+1)=\frac{n!}{(n-m)!}Anm=n(n−1)(n−2)...(n−m+1)=(n−m)!n!
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int mod=1e9+7;
const int MAXN=200000;
LL fact[MAXN],inv[MAXN],factinv[MAXN];
LL C(LL n,LL m)
{
return fact[n]*factinv[m]%mod*factinv[n-m]%mod;
}
LL A(LL n,LL m)
{
return fact[n]%mod*factinv[n-m]%mod;
}
int main()
{
LL n,m;
fact[0]=inv[0]=factinv[0]=1;
fact[1]=inv[1]=factinv[1]=1;
for(int i=2;i<MAXN;i++)
{
fact[i]=(fact[i-1]%mod*i%mod)%mod;
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
factinv[i]=factinv[i-1]*inv[i]%mod;
}
cin>>n>>m;
cout<<C(n,m)<<" "<<A(n,m)<<endl;
return 0;
}
组合数性质
- Cnm=Cnn−mC_n^m=C_n^{n-m}Cnm=Cnn−m
- Cnm=Cn−1m+Cn−1m−1C_n^m=C_{n-1}^m+C_{n-1}^{m-1}Cnm=Cn−1m+Cn−1m−1又被称为杨辉三角递推式
- Cn0+Cn1+...+Cnn=2nC_n^0+C_n^1+...+C_n^n=2^nCn0+Cn1+...+Cnn=2n
- Cnm=(−1)m∗Cm−n−1mC_n^m=(-1)^m*C_{m-n-1}^{m}Cnm=(−1)m∗Cm−n−1m
Lucas定理
Cnm≡Cn%pm%p∗Cn/pm/pC_n^m\equiv C_{n \% p}^{m\%p}*C_{n/p}^{m/p}Cnm≡Cn%pm%p∗Cn/pm/p
其中p为质数
LL C(LL n,LL m)
{
if(n<m) return 0;
return fact[n]*factinv[m]%mod*factinv[n-m]%mod;
}
LL Lucas(LL n,LL m,LL p)
{
if(n<p&&m<p) return C(n,m);
return C(n%p,m%p)*Lucas(n/p,m/p,p)%p;
}
卡特兰数(Catalan数列)
给定n个0和1,按某种顺序排成长度为2n的序列,满足任意前缀0的个数都不少于1的个数的序列的数量:
C2nn−C2nn−1=(2n)!n!n!−(2n)!(n−1)!(n+1)!=C2nnn+1=CatnC_{2n}^{n}-C_{2n}^{n-1}=\frac {(2n)!}{n!n!}-\frac{(2n)!}{(n-1)!(n+1)!}=\frac{C_{2n}^n}{n+1}=Cat_nC2nn−C2nn−1=n!n!(2n)!−(n−1)!(n+1)!(2n)!=n+1C2nn=Catn
LL C(LL n,LL m)
{
return fact[n]*factinv[m]%mod*factinv[n-m]%mod;
}
cout<<C(2*n,n)-C(2*n,n-1)<<endl;
错排公式
错排:基本上可以理解为1~n的排列满足ai!=ia_i!=iai!=i的方案数
递推式
Dn=(n−1)∗(Dn−1+Dn−2)D_n=(n-1)*(D_{n-1}+D_{n-2})Dn=(n−1)∗(Dn−1+Dn−2)
其他
范德蒙德卷积
从数量为n和m的两个堆中一共选择k个物品
∑i=0kCniCmk−i=Cn+mk\sum_{i=0}^kC_{n}^iC_m^{k-i}=C_{n+m}^k∑i=0kCniCmk−i=Cn+mk
本文介绍了组合数的模板C(n,m)和An(m),展示了C(n, m)的递推关系和杨辉三角,以及Lucas定理的应用。内容涵盖了 Lucas 函数实现、卡特兰数列、错排公式和范德蒙德卷积等关键概念。
195

被折叠的 条评论
为什么被折叠?



