基本组合数

本文介绍了组合数的模板C(n,m)和An(m),展示了C(n, m)的递推关系和杨辉三角,以及Lucas定理的应用。内容涵盖了 Lucas 函数实现、卡特兰数列、错排公式和范德蒙德卷积等关键概念。

组合数模板

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=Cn1m1+Cnm1=m!(nm)!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(n1)(n2)...(nm+1)=(nm)!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=Cnnm
  • Cnm=Cn−1m+Cn−1m−1C_n^m=C_{n-1}^m+C_{n-1}^{m-1}Cnm=Cn1m+Cn1m1又被称为杨辉三角递推式
  • 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)mCmn1m

Lucas定理

Cnm≡Cn%pm%p∗Cn/pm/pC_n^m\equiv C_{n \% p}^{m\%p}*C_{n/p}^{m/p}CnmCn%pm%pCn/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_nC2nnC2nn1=n!n!(2n)!(n1)!(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=(n1)(Dn1+Dn2)

其他

范德蒙德卷积

从数量为n和m的两个堆中一共选择k个物品
∑i=0kCniCmk−i=Cn+mk\sum_{i=0}^kC_{n}^iC_m^{k-i}=C_{n+m}^ki=0kCniCmki=Cn+mk

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值