排列组合的基础(入门必备!!)

一、排列

1、不可重复排列

A n r   =   n ( n − 1 ) ( n − 2 ) . . . ( n − r + 1 ) {A}^{r}_{n}\, =\, n(n-1)(n-2)...(n-r+1) Anr=n(n1)(n2)...(nr+1)

A n r   =   n ! ( n   −   r ) ! {A}^{r}_{n}\, =\, \frac {n!} {(n\, -\, r)!} Anr=(nr)!n!

2、可重复排列

n r {n}^{r} nr

3、圆排列

**定义:**有一组元素,将其排成一个圆,这种排列叫做圆排列或项链排列。

  • ​ n个数的圆排列为(n-1)!
  • ​ n个不同数中取r个的圆排列:

P n r r   =   A n r r   =   n ! ( n − r ) !   × r \frac {{P}^{r}_{n}} {r}\, =\, \frac {{A}^{r}_{n}} {r}\, =\, \frac {n!} {(n-r)!\, \times r} rPnr=rAnr=(nr)!×rn!

4、不尽相异元素全排列

定义:如果n个元素里,有p个元素相同,又有q个元素相同,…,又有r个元素相同(p+q+…+r≤n),则它们的所有排列种数为:
n ! p ! q ! . . . r ! \frac {n!} {p!q!...r!} p!q!...r!n!
uva 11076

二、组合

1、不可重组合数

C n r   =   n ! r ! ( n − r ) ! {C}^{r}_{n}\, =\, \frac {n!} {r!(n-r)!} Cnr=r!(nr)!n!

2、可重组合数(隔板法)

转换思路,既然要抽r次,就要放回r-1次,最后一次的放回对抽样结果无影响

那么就变成我把r-1个物品放入n里,然后一次抽取k个。
H n r   =   C n + r − 1 r   =   ( n + r − 1 ) ! r ! ( n − 1 ) ! {H}^{r}_{n}{\, =\, C}^{r}_{n+r-1}\, =\, \frac {(n+r-1)!} {r!(n-1)!} Hnr=Cn+r1r=r!(n1)!(n+r1)!

3、不相邻组合数

3.1从n个球中选出r个球,要求r个球互不相邻

分析:

  • 当n<2r-1时,取法为0种
  • 当n≥2r-1时,取法为

   C n − r + 1 r   {\, \, C}^{r}_{n-r+1}\, Cnr+1r

理解思路:先从n中拿取r-1个球,然后我们在剩下的n-r+1个球中任取r个球,一开始的r-1个球填入r个球的空位中,这样就可以使r个球互不相邻。

3.2从n个围成一圈的球中选出r个球

分析:

当n<2r时,取法为0种

当n≥2r时,取法为
n C n − r r n − r \frac {{nC}^{r}_{n-r}} {n-r} nrnCnrr
理解思路: 无论怎么取,都是两种情况, 一种包括一号,另一种不包括一号。

包括一号:
C n − r − 1 r − 1 {C}^{r-1}_{n-r-1} Cnr1r1
不包括一号:
C n − r r {C}^{r}_{n-r} Cnrr

4、常用组合函数公式

$$
{C}^{r}{n}, =, {C}^{r}{n-1}, +, {C}^{r-1}_{n-1}

$$

C n r   =   C n n − r   {C}^{r}_{n}\, =\, {C}^{n-r}_{n}\, Cnr=Cnnr

C n r + 1   =   n − r r + 1 C n r   {C}^{r+1}_{n}\, =\, \frac {n-r} {r+1}{C}^{r}_{n}\, Cnr+1=r+1nrCnr

板子

一、排列组合数

1、费马小定理(要求模数为质数)

复杂度O(nlogn),当n到1e7时就炸,这时候要用线性递推。

typedef long long ll;
const ll maxn = 1e6+10, mod = 1e9+7;
ll Jc[maxn];
void calJc()    //求maxn以内的数的阶乘
{
    Jc[0] = Jc[1] = 1;
    for(ll i = 2; i < maxn; i++)
        Jc[i] = Jc[i - 1] * i % mod;
}
ll pow(ll a, ll n, ll mod)    //快速幂 a^n % p
{
    ll ans = 1;
    while(n)
    {
        if(n & 1) ans = ans * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return ans;
}
ll niYuan(ll a)   //费马小定理求逆元
{
    return pow(a, mod - 2, mod);
}
ll C(ll n, ll r)    //计算C(n, r)
{
    return Jc[n] * niYuan(Jc[r]) % mod
        * niYuan(Jc[n - r]) % mod;
}
ll A(ll n, ll r)
{
    return Jc[n] * niYuan(Jc[n-r])%mod;
}

2、拓展欧几里得(不要求模数为质数)

复杂度同上,关键点在他的模数不需要是质数。

typedef long long ll;
const ll maxn = 1e6+10, mod = 1e9+7;
ll Jc[maxn];
void calJc()    //求maxn以内的数的阶乘
{
    Jc[0] = Jc[1] = 1;
    for(ll i = 2; i < maxn; i++)
        Jc[i] = Jc[i - 1] * i % mod;
}
void exgcd(ll a, ll b, ll &x, ll &y)    //拓展欧几里得算法
{
    if(!b) x = 1, y = 0;
    else
    {
        exgcd(b, a % b, y, x);
        y -= x * (a / b);
    }
}
ll niYuan(ll a)   //求a对b取模的逆元
{
    ll x, y;
    exgcd(a, mod, x, y);
    return (x + mod) % mod;
}
ll C(ll n, ll r)    //计算C(n, r)
{
    return Jc[n] * niYuan(Jc[r]) % mod
        * niYuan(Jc[n - r]) % mod;
}
ll A(ll n, ll r)
{
    return Jc[n] * niYuan(Jc[n-r])%mod;
}

3、逆元-线性递推(p是质数)

typedef long long ll;
const ll maxn = 1e7+10, mod = 1e9+7;
ll Jc[maxn];
ll inv[maxn+5];
void getInv(ll mod)
{
    inv[1]=1;
    for(int i=2;i

资料参考:

(24条消息) ACM-组合数学完全总结(知识点+模板)_Ogmx的博客-CSDN博客_组合数学

你可能感兴趣的:(笔记,算法)