笔记——排列组合

蓝月の笔记——排列组合篇

摘要

万恶的数学!

Part 1 加乘原理

小学奥数内容

加法原理:当多个方案并列(即互不影响)时,总方案数为各个方案数之和

例:共有 k 种交通工具可以从A地到B地,第 i 种交通工具有 ai 班次,那么从A地到B地的总方案数为 i=1kai

乘法原理:当多个方案分步完成时,总方案数为各步方案数之积

例:从 1 地到 k 地,规定只能从 i 地单项移动到 i+1 地,且有 ai 种路线,那么从 1 地到 k 地的总方案数为 i=1k1ai

Part 2 排列组合数

排列数

n 个小朋友种选择 k 个小朋友排成一队的方法数,记为 Ank

公式推导

选第 1 个小朋友有 n 种方案,选第 2 个小朋友有 n1 种方案(因为有一个被选了),,选第 k 个小朋友有 nk+1 种方案

根据乘法原理,Ank=i=nk+1ni=n!(nk)!

组合数

n 个小朋友种选择 k 个小朋友的方法数(不考虑顺序),记为 Cnk

公式推导

选出 k 个不考虑顺序的小朋友,相当于选出 k 个考虑顺序的小朋友再打乱顺序,除以顺序数即可

Cnk=Ankk!=n!(nk)!k!

对称性

n 个里面选 k 个相当于在 n 个里面选 nk 个丢掉,所以 Cnk=Cnnk

多重组合数

实际上是全排列,有 k 对多胞胎,共 n 个人,第 i 对有 ai 个人,因为每一对多胞胎之间长得太像了,所以在给他们排队时会把他们是为同一个人(即交换位置只算做一种方案),排队的方案数即为多重组合数,记为 (na1,a2,,ak)

公式推导

假设多胞胎交换位置算作多种方案,答案显然为 n!

每一对多胞胎之间都有 ai! 种先后位置关系,将这些重复计算除掉即可,(na1,a2,,ak)=n!i=1kai!

Part 3 插板法

可以理解为求不定方程 i=1kxi=n 的解的数量

xi>0

n1 之间的 n1 空插 k1 个板子,分成的 k 个空间的 1 的个数为每一个 xi 的值

答案为 Cn1k1

xi0

n1 后补 k1,再插 k1 个板子,最后拿掉补的 k1,就可以留出 01 的区间了

答案为 Cn+k1k1=Cn+k1n(对称性)

xiai

t=ai,si=xiai

n1 后补 t1,此时可以保证 k 个区间内都达到了 xiai 的要求,那么原方程转化为 i=1k(si+ai)=n,则 i=1ksi=nt(si0),变成了 xi0 的形式,按公式求解即可

答案为 Cnt+k1nt

Part 4 杨辉三角&二项式定理

杨辉三角:

1

11

121

1331

14641

通过瞪眼法可以知道,杨辉三角的第 ij 个数为 Ci1j1

再次通过瞪眼法可以知道,杨辉三角最左一列和最右一列都是 1,其它数都是它左上的数和右上的数的和,那么组合数的递推式就是 Cij=Ci1j+Ci1j1

再再次通过瞪眼法,可以发现杨辉三角的第 i 列为 (x+y)i1 展开后每一项的系数,这就是二项式定理,用公式表示为:

(x+y)n=i=0nCnixiyni

将二项式推广为多项式,同理可得 (i=1kxi)n=(a1,a2,,ak)P((na1,a2,,ak)i=1kxiai)

我们称 k 元组 (a1,a2,,ak) 满足性质 P,当且仅当 i[1,k],xi=ai 是不定方程 1ikxi=n 的一组解

Part 5 圆排&项链排&错排

圆排列

n 个人坐在一个圆桌上吃饭,排位置的方案数就是圆排列数(旋转前后算一种方案)

显然为全排列除以旋转次数,Rn=Annn=(n1)!

项链排列

n 个不同的珠子串成一个项链,可以串成的项链数量就是项链排列数(旋转、翻转前后算一种方案)

在圆排列的基础上除以两种翻转方式,Nn=Rn2=(n1)!2

错位排列(信封问题)

例题终于有题了

p1n 的一个排列,如果 i[1,n],pii,那么我们称 pn 的一个错位排列

错排数可以使用递推求解,Oi Wiki上已经讲的很清楚了,我就(懒)不(得)讲了

Code:

d[0] = 1, d[1] = 0, d[2] = 1;
for (int i = 3; i < kMaxN; i++) {
  d[i] = ((i - 1) * ((d[i - 1] + d[i - 2]) % kP)) % kP;
}

Part 6 抽屉原理

小学奥数内容

n 个抽屉和 n+1 个小朋友,把小朋友放到抽屉里(?),至少有一个抽屉里有 2 个小朋友,证明留作课后习题

推广后同理可得,有 k 个抽屉和 n 个小朋友,再把小朋友放到抽屉里,则至少有一个抽屉里有 nk 个小朋友,证明留作课后习题 2

Part 7 容斥原理

怎么tm还是小学奥数内容

x 个小朋友是男的,有 y 个小朋友是女的,有 z 个小朋友既是男的也是女的(?),则小朋友的数量就是 x+yz,证明如图显然

用集合形式表示即为 |AB|=|A|+|B||AB|

推广到一般形式:|i=1nAi|=p=1m((1)p11r1r2rpm|i=1pAri|)

例题

先使用背包求出无限制的情况下所有价格的方案数,再求出用每一种硬币付不起的最小价格,最后按公式容斥即可(位运算是个好东西,可惜我不会)

// BLuemoon_
#include <bits/stdc++.h>

using namespace std;
using LL = long long;

const int kMaxN = 1e5 + 5, kN = 4 + 5;

LL n, t, c[kN], a[kN], s, dp[kMaxN], f[kN], ans;

int main() {
  cin >> c[1] >> c[2] >> c[3] >> c[4], dp[0] = 1;
  for (int i = 1; i <= 4; i++) {
    for (int j = c[i]; j <= 1e5; j++) {
      dp[j] += dp[j - c[i]];
    }
  }
  for (cin >> t; t; t--, ans = f[5] = 0) {
    cin >> a[1] >> a[2] >> a[3] >> a[4] >> s, ans += dp[s];
    for (int i = 1; i <= 4; i++) {
      f[i] = c[i] * (a[i] + 1), (s >= f[i]) && (ans -= dp[s - f[i]]), f[5] += f[i];
    }
    for (int i = 1; i <= 3; i++) {
      for (int j = i + 1; j <= 4; j++) {
        (s >= (f[i] + f[j])) && (ans += dp[s - f[i] - f[j]]);
      }
    }
    for (int i = 1; i <= 2; i++) {
      for (int j = i + 1; j <= 3; j++) {
        for (int l = j + 1; l <= 4; l++) {
          (s >= (f[i] + f[j] + f[l])) && (ans -= dp[s - f[i] - f[j] - f[l]]);
        }
      }
    }
    (s >= f[5]) && (ans += dp[s - f[5]]);
    cout << ans << '\n';
  }
  return 0;
}

Part 8 卡特兰数

我们来看一些问题:

1.

在坐标系中从 (0,0)(n,n),只能向右或向上走,且不能超过 l:y=x,问有多少种路径

2.

圆上有 2n 个均匀排列的点,将它们两两相连得到 n 条弦,问有多少种连接方式使这 n 条弦互不相交

3.

n 个节点可以构造的二叉树个数

这些问题的答案都是卡特兰数,写作 Hn,我们知道 H0=1,H1=1,H2=2,H3=5,H4=14

To be continued

posted @   BluemoonQwQ  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示