排列组合与二项式基础

排列组合相关与二项式基础

一、加乘原理

1.加法原理

做一件事,完成他的方法可以分为\(n\)个互不相交的类,每一类有\(a_i\)中方法,则完成这件事一共有
\[ a_1+a_2+...+a_n \]
种方法。

加法原理的核心思想就是,把“整体”分作每个“部分”,分别对每个部分进行计数,最后求和。

2.乘法原理

若完成一件事有\(n\)个步骤,每个步骤有\(a_i\)种方法,则完成这件事一共有
\[ a_1\times a_2 \times ...\times a_n \]
种方法。

乘法原理的核心思想就是,把这件事分成几个步骤,且每一个步骤的方法数目比较好确定。

加乘原理很简单,你们小学奥数学的都比本蒟蒻强,但加乘原理是计数的基础。

二、排列与组合

1.排列

一般地,从\(n\)个不同元素中取出\(m(m≤n)\)个元素,按照一定的顺序排成一列,叫做从\(n\)个元素中取出\(m\)个元素的一个排列,记作\(A_n^m\)(或者记作\(P_n^m\))。

由乘法原理得:
\[ A_n^m=n\times(n-1)\times (n-2)\times\dots\times (n-m+1) \]
特别地,如果\(m=n\),则我们就可以得到关于\(n\)全排列
\[ A_n^n=n\times(n-1)\times(n-2)\times \dots \times 1=n! \]
我们约定\(0!=1\),则排列公式可写为
\[ A_n^m=\frac{n!}{(n-m)!} \]
这也是这个公式的更为常见的形式。

2.组合

一般地,从\(n\)个不同的元素中,任取\(m(m≤n)\)个元素为一组,叫作从\(n\)个不同元素中取出\(m\)个元素的一个组合,记作\(C_n^m\)(或者记作\(\binom{n}{m}\)

组合和排列数的区别是,组合数要求无序

所以我们可以得到:
\[ C_n^m=\frac{A_n^m}{m!} \]
展开我们可以得到:
\[ C_n^m=\frac{n!}{m!(n-m)!} \]
关于排列和组合还有一些经典的数学问题,由于纯数学不是我们讨论的重点,这里仅给出结论,需要证明的可以自行在网上查阅。

1.可重排列:\(n^m\)

2.有限元素的可重排列:\(\frac{n!}{n_1!\times n_2!\times \dots \times n_m!}\)

3.可重组合:\(C_{n+m-1}^m\)

4.有限元素的可重组合:\(C_{m+k-1}^{k-1}\)(这里\(k\)小于等于每个元素的数量)

三、二项式相关

1.二项式系数与二项式定理

组合数\(C_n^m\)也被称作二项式系数,它有三重面目:

1.组合意义:\(n\)个不同元素的\(m\)-组合

2.显示表示:\(C_n^m=\frac{n!}{m!\times (n-m)!}\)

3.二项展开式的系数,即有恒等式
\[ (x+y)^n=\sum^n_{i=0}C_n^i\times x^n \times y^{n-i} \]
上面的恒等式称为二项式定理。

二项式定理的证明有很多种,这里给出一种基于其组合意义的证明:

显然
\[ (x+y)^n=\begin{matrix}\underbrace{(x+y)(x+y)\dots(x+y)} \\ n个(x+y) \end{matrix} \]
对于其中的一项\(x^iy^{n-i}\),相当于是从\(n\)\((x+y)\)中任意取\(i\)个,从中挑出\(x\),再在剩下的\((x+y)\)中挑出\(y\)来相乘,所以该项的系数是\(C_n^i\),由此不难验证二项式定理。

2.组合恒等式

常见的组合恒等式有以下几个,它们大多都和二项式相关

1.(对称性

\[ C_n^m=C_n^{n-m} \]

2.(递推公式

\[ C_n^m=C_{n-1}^m+C_{n-1}^{m-1} \]

3.

\[ C_n^0+C_n^1+C_n^2+\dots+C_n^n=2^n \]

4.(单峰性)若\(n\)是偶数,则

\[ C_n^0<C_n^1<\dots<C_n^{\frac{n}{2}}>\dots>C_n^{n-1}>C_n^n \]
\(n\)是奇数,则

\[ C_n^0<C_n^1<\dots<C_n^{\frac{n-1}{2}}=C_n^{\frac{n+1}{2}}>\dots>C_n^{n-1}>C_n^n \]

5.

\[ C_n^0+C_{n+1}^1+\dots+C_{n+k}^k=C_{n+k+1}^{k+1} \]

6.

\[ C_n^0-C_n^1+C_n^2+\dots+(-1)^nC_n^n=0 \]

7.(范德蒙恒等式

\[ C_{m}^0C_n^k+C_m^1C_n^{k-1}+C_m^2C_n^{k-2}+\dots+C_m^kC_n^0=C_{n+m}^k \]

8.

\[ C_n^k=\frac{n}{k}C_{n-1}^{k-1} \]

9.

\[ C_n^kC_k^m=C_n^mC_{n-k}^{m-k} \]
它们的证明如下:

1.从\(n\)个数中选\(m\)个数,他们呢构成了一个,剩下没选的数也构成了一个集合,等式一显然成立。

2.假设我们现在面对的是第\(n\)号元素,我们无非就两种选择:选和不选。

如果我们选择第\(n\)号元素,那么我们就需要在前\(n-1\)个元素中选\(m-1\)个元素。

如果我们不选择第\(n-1\)号元素,那么我们就需要在前\(n-1\)一元素中选\(m\)个元素。

由加法原理不难验证等式2的正确性。

3.从\(n\)个元素中取任意个元素,要么选,要么不选,所以是\(2^n\)种。

我们也可以看成取0个,取1个, 取2个,...,取\(n\)个,就相当于等式的左边。

所以等式3成立。

4.我们完全可以通过暴力展开的形式来证明,或者我们结合性质1也不难证明

5.反复运用递推公式,我们有:
\[ C_n^0+C_{n+1}^1=C_{n+1}^0+C_{n+1}^1=C_{n+2}^1\\ C_{n+2}^1+C_{n+2}^2=C_{n+3}^2\\ C_{n+3}^2+C_{n+3}^3=C_{n+4}^3\\ \cdots\\ C_{n+k}^{k-1}+C_{n+k}^k=C_{n+k+1}^k \]
6.在二项式定理中取\(x=1\)\(y=-1\)即可。

推论:
\[ C_n^0+C_n^2+C_n^4+\dots=C_n^1+C_n^3+C_n^5+\dots \]
7.同样地,我们仍然可以暴力展开证明,但很麻烦。

我们仍然考虑从它的组合意义上证明。

如果我们从\(n\)个zrw和\(m\)个lsy中任意选取\(k\)个人组成一组,显然,答案为\(C_{n+m}^k\)

所有的方案可以分为\(k+1\)个类:第\(i\)类由\(i\)个zrw和\(k-i\)个lsy组成一组(\(i\in[0,k]且i\in \Z\)),每一类的答案就是\(C_n^iC_m^{k-i}\),根据加法原理不难验证等式7的正确性。

8&9.暴力展开得
\[ \begin{align} C_n^kC_k^m &=\frac{n!}{k!(n-k)!}\times\frac{k!}{m!(k-m)!}\\ &=\frac{n!}{m!(n-m)!}\times\frac{(n-m)!}{(k-m)!(n-k)!}\\ &=C_n^mC_{n-k}^{m-k} \end{align} \]
\(k=1\)时即为等式8

3.二项式反演

这部分可以看看本蒟蒻的一篇博客:二项式反演笔记

四、组合数的求法

1.递推公式法

我们先令\(C_i^0=1\),通过组合数的递推公式
\[ C_n^m=C_{n-1}^m+C_{n-1}^{m-1} \]
即可求得

时间复杂度为\(O(n^2)\)

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];
}

2.显示表示法

注:除第一种方法意外,其他所有方法均是在模数意义下求组合数的值
\[ C_n^m=\frac{n!}{m!(n-m)!} \]
我们可以先求分子\(n!\)的值,然后对分母\(m!(n-m)!\)来求模\(p\)意义下的逆元,最后相乘即可。

时间复杂度为\(O(n)\)

如果我们是批量求组合数的话,我们可以做到更优。

我们先预处理\(i!\)以及\(i!\)\(p\)意义下的逆元,时间复杂度为\(O(n)\)

(求逆元时第一个数为\(O(\log n)\),之后根据阶乘逆元的性质我们可以在\(O(n)\)的时间内求得)

然后我们可以在\(O(1)\)的时间内回答询问:f[n] * invf[m]%p * invf[n-m]%p

关于预处理阶乘逆元,有
\[ invf_{i} \equiv invf_{i+1}\times (i+1) \pmod p \]
证明:
\[ f_i \times invf_i \equiv 1 \pmod p \]

\[ f_{i-1}\times i \times invf_i \equiv 1 \pmod p \]

3.Lucas定理

\(p\)是质数,则对于\(1\le m\le n\),有
\[ C_n^m\equiv C_{n \bmod p} ^{m \bmod p}\times C_{\frac{n}{p}}^{\frac{m}{p}} \pmod p \]
也就是把\(n\)\(m\)进行\(p\)进制分解,然后分别求它们每一位对应的组合数的值。

我们可以用类似于生成函数的方法来证明Lucas定理。

\(n=ap+r_1\)\(m=bp+r_2\)

我们取这样一个式子:
\[ \begin{align} (1+x)^n &=(1+x)^{ap+r_1}\\ &=((1+x)^p)^a\times (1+x)^{r_1} \end{align} \]
\(p\)为质数时,对于\(i\in[1,p-1]且i\in N^*\),我们可以得到
\[ C_p^i\equiv0 \pmod p \]
(结合组合数的显示表示不难证明)

于是
\[ \begin{align} ((1+x)^p)^a\times (1+x)^{r_1}&\equiv(1+x^p)^a\times(1+x)^{r_1}\\ &\equiv\sum_{i=0}^aC_a^ix^{pi} \times\sum_{j=0}^{r_1}C_{r_1}^jx^{r_1} \pmod p \end{align} \]
(结合二项式定理不难理解)

整理得
\[ \sum_{i=0}^nC_n^ix^i\equiv\sum_{i=0}^aC_a^ix^{pi} \times\sum_{j=0}^{r_1}C_{r_1}^jx^{r_1} \pmod p \]
对于左边展开的一项\(x^{bp+r_2}\),他对应的系数是\(C_n^{bp+r_2}\)

而当且仅当右边的\(i=b\)\(j=r_2\)时才能对应左边的\(x^{bp+r_2}\),此事它所对应的系数为\(C_a^b\times C_{r_1}^{r_2}\)

整理得
\[ C_n^m\equiv C_{n \bmod p} ^{m \bmod p}\times C_{\frac{n}{p}}^{\frac{m}{p}} \pmod p \]
证毕。

Lucas定理一般用于模数为质数,且\(n\)\(m\)都较大时。它需要与上面得两种方法配合起来使用。

来道模板题吧:P3807 【模板】卢卡斯定理

Code:

#include<bits/stdc++.h>
#define FUCK puts("FUCK")
#define int long long
using namespace std;
const int maxn=1e6+5;
int T;
int n,m,p;
int f[maxn];
inline int ksm(int x,int y){
    if(!y) return 1;
    if(y==1) return x%p;
    int tmp=ksm(x,y/2);
    tmp=(tmp*tmp)%p;
    if(y&1) return (tmp*x)%p;
    else return tmp;
}
inline int calc(int x,int y){
    if(y>x) return 0;
    return f[x]*ksm(f[y],p-2)%p*ksm(f[x-y],p-2)%p;
}
inline int Lucas(int x,int y){
    if(!y) return 1;
    return (calc(x%p,y%p)*Lucas(x/p,y/p))%p;
}
signed main(){
    scanf("%lld",&T);
    while(T--){
        scanf("%lld%lld%lld",&n,&m,&p);
        f[0]=1;
        for(int i=1;i<=p;i++) f[i]=(f[i-1]*i)%p;
        printf("%lld\n",Lucas(n+m,n));
    }
    return 0;
}

另外,求组合数还有一种方法:exLucas。不过这种方法相对上面的方法比较难写,一般直接用Lucas就够了。

如有不足尽请指正,谢谢!

参考资料:

1.华东师范大学出版社 《奥数教程》高中第三分册

2.李煜东 《算法竞赛进阶指南》

转载于:https://www.cnblogs.com/ybwowen/p/11216720.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值