椰程信奥·互动课件 专题19·数学专题2:计数原理、排列组合、同余与素数筛
10:00 1 / 14
🧭 椰程信奥 · CSP复赛专题系列

专题19 · 数学专题2

本讲四块:加法原理与乘法原理、排列与组合、同余与取模、素数筛法。
前三块决定你会不会数数,最后一块决定你数得快不快。
两道真题:素数个数(线性筛)、组合数取模(杨辉三角)。

分类用加法 · 分步用乘法 排列有序 · 组合无序 埃氏筛 · 线性筛 · 边算边取余
基础

什么时候加,什么时候乘

所有计数题都从这两条出发:加法是「分类」,乘法是「分步」加法原理 · 分类(并列,走一条就行)A3 类办法 → 总数 = 各类的和乘法原理 · 分步(串联,每步都要走)1234每步的选择数相乘分步之间必须「互不干扰」,否则不能乘判断口诀:能「二选一」就加,要「先…再…」就乘。

加法原理(分类)

做一件事有若干类互不重叠的方法,每类分别有 m₁、m₂ … 种 → 总数 = m₁ + m₂ + …
例:北京到上海,飞机 3 班 + 高铁 5 班 + 大巴 2 班 = 10 种。

乘法原理(分步)

做一件事要分几步完成,每步分别有 m₁、m₂ … 种 → 总数 = m₁ × m₂ × …
例:上衣 4 件 × 裤子 3 条 × 鞋 2 双 = 24 套。

⚠️ 判断口诀: "要么…要么…"(任选一类就能完成)→ 加法; "先…再…"(每步都要做)→ 乘法。
最常犯的错:把"分步"当成"分类"相加,或者把"分类"当成"分步"相乘。
3D🎲 计数 = 每个交叉点都是「左 + 上」🖱 拖拽旋转 · 双击复位
为什么用 3D:加法原理在网格上就是「柱高 = 左 + 上」。立体柱阵越高越靠中间,组合数 C(n,k) 的分布形状自己就出来了。
动画①

同一件事,加法还是乘法

切换场景,看总数到底是"相加"还是"相乘"。
基础

唯一的区别:有没有顺序

排列 A(n, r):有序

从 n 个不同元素里取 r 个排成一列。
A(n,r) = n! / (n−r)! = n×(n−1)×…×(n−r+1)
例:5 人选正、副班长 → A(5,2) = 20(张三正/李四副 ≠ 李四正/张三副)。

组合 C(n, r):无序

从 n 个不同元素里取 r 个凑成一组,不分先后。
C(n,r) = A(n,r) / r! = n! / (r!·(n−r)!)
例:5 人选 2 人组队 → C(5,2) = 10(两人一组,无正副之分)。

两条必须记住的性质

① C(n,r) = C(n,n−r) —— 选 r 个留下 = 选 n−r 个丢掉,可用来把 r 缩小一半。
② C(n,r) = C(n−1,r) + C(n−1,r−1) —— 杨辉三角,也是组合数 DP 求法的基础。
含义:面对第 n 个元素,不选它(前 n−1 个里选 r 个)或 选它(前 n−1 个里再选 r−1 个),两类互斥 → 加法。

动画②

为什么组合要除以 r!

从 4 人里选 2 个:排列 12 种,组合只有 6 种 —— 差在"顺序"。
动画③

C(n,r) = 上 + 左上

每一格 = 正上方 + 左上方。边界 C(i,0) = C(i,i) = 1。
基础

边算边取余,别等最后

同余的定义

若 a % m == b % m,称 a 与 b 模 m 同余,记作 a ≡ b (mod m)。
性质:自反、对称、传递。

运算可"先取余再算"

(a + b) % m = (a%m + b%m) % m
(a × b) % m = (a%m × b%m) % m
所以可以每一步都取余,结果不变。

为什么必须边算边取余

组合数、阶乘、大数乘法增长极快:100! 有 158 位,任何整数类型都放不下。
但如果我们只关心它对 m 的余数,就可以每乘一次就取一次余,数字永远不超过 m。
这就是"大数乘法取模"类题目的唯一解法。

long long ans = 1;
for (int i = 1; i <= n; i++) ans = ans * i % MOD;   // 每步取余
⚠️ 两个坑: ① 减法取模可能为负 → (a - b + MOD) % MOD; ② a × b 本身在取余前就可能溢出 long long → 用更大的类型或先分解。
核心

三种筛法,一个比一个聪明

① 普通(逐个试除)

对每个数独立判定是否质数。
复杂度 O(n√n)。
n = 10⁵ 时约 3×10⁷ 次 → 勉强/超时。

② 埃氏筛

从 2 开始,把每个质数的倍数划掉。
复杂度 O(n log log n)。
缺点:合数会被重复划(如 12 被 2 和 3 各划一次)。

③ 线性筛(欧拉筛)

让每个合数只被最小质因子划一次。
复杂度 O(n)。
关键:if (i % p == 0) break;

for (int i = 2; i <= n; i++){
    if (!isComp[i]) primes.push_back(i);       // 没被划掉 → 质数
    for (int p : primes){
        if ((long long)i * p > n) break;       // 超范围就停
        isComp[i * p] = true;
        if (i % p == 0) break;                 // ★ 保证只用最小质因子筛
    }
}
⚠️ 那一行 break 是线性筛的灵魂: 当 p 能整除 i 时,说明 p 是 i 的最小质因子, 后续更大的质数再去筛 i*p' 时,该合数的最小质因子仍是 p,会被重复筛 → 必须停。
动画④

数一数每个合数被划了几次

切到「埃氏」看重复划,切到「线性」看每个合数只被划一次。
动画⑤

每乘一次就取一次余

点「乘一步」:每次乘完立刻取余,数字永远不爆炸。
辨析

本讲五个高频失分点

① 加法乘法混用

❌ 把分步当分类相加。
✅ "要么…要么…"→加;"先…再…"→乘。

② 排列组合搞混

❌ 该除以 r! 却没除(把组合当排列)。
✅ 问自己"交换顺序算不算同一种"。

③ 最后才取模

❌ 先算出 100! 再取模 → 溢出。
✅ 每步取余。

④ 线性筛漏 break

❌ 缺 if (i % p == 0) break; → 退化成埃氏筛。
✅ 必须有。

知识树

数学2 ─┬─ 计数原理:加法(分类)/ 乘法(分步)
    ├─ 排列 A(n,r) 有序 / 组合 C(n,r) 无序(÷ r!)
    ├─ 同余:边算边取余
    └─ 筛法:试除 O(n√n) → 埃氏 O(n log log n) → 线性 O(n)

拿分

一道题 100 分是分档给的——不会正解也要先拿保底

复赛一道题的 100 分由十几到二十几个测试点组成, 前面几档专门为「没想出正解的人」准备。四道题各拿 30~40 分, 加起来往往就是一等奖和二等奖的分界。

第 1 档 特判 5~10 分 约 2 分钟 第 2 档 暴力 20~30 分 约 8 分钟 第 3 档 特殊性质 40~60 分 约 15 分钟 第 4 档 正解 100 分 约 25 分钟

① 特判档:先别想算法,看数据范围表

题目给的数据范围表就是出题人给你的送分清单。看到「n = 1」「只有一组数据」这类一行, 就先写个 if 直接输出答案。2 分钟换 5~10 分,全场最划算。

② 暴力档:按题意最直白地写一遍

多重循环、DFS 全枚举、朴素 O(n³)……不要优化,只要保证最小那档全对。 它既是保底分,又是后面对拍的标尺——没有它你无法证明正解是对的。

③ 特殊性质档:题目里那句「若……」

常见的送分性质:数据已经有序、所有值完全相同、规模小到可以 O(n²)、 只出现一种类型。题目写出来就是让你拿的,专门写一份即可。

④ 正解档:思路定了,就赢了八成

考场上的时间几乎都花在想思路上,不是写代码。写完先跑样例, 再用第 ② 档的暴力版造小数据对拍——这是唯一能证明你思路对的办法。

考场纪律:每档设时间上限,到点还没调通就 立刻提交当前版本,保住已有分数,再往上冲。最常见的翻车是"正解写了 50 分钟没过,连暴力分都没交上去"。
拿分

本讲 2 道题,各自的四档怎么走

素数个数 · PRIMECNT

第1档 · 2 分钟
n < 2 → 0

第2档 · 8 分钟
对每个数试除到 √i,n ≤ 10⁴ 稳过

第3档 · 10 分钟
只判奇数(除 2 外全是合数)

第4档 · 15 分钟
埃氏筛 / 欧拉筛,O(n log log n)

组合数(取模) · COMBINE

第1档 · 2 分钟
m == 0 或 m == n → 1;m > n → 0

第2档 · 8 分钟
用 C(n,m) = C(n−1,m−1) + C(n−1,m) 递推,n ≤ 1000 稳过

第3档 · 10 分钟
模数是质数且 n ≤ 2000 → 杨辉三角递推就够

第4档 · 15 分钟
阶乘 + 逆元(费马小定理):fac[n]·inv(m)·inv(n−m) % MOD

50 分钟时间盒(一题的节奏):
0–5 分钟 读题 + 圈出数据范围表里最小的那几档 → 5–15 分钟 写完第 1、2 档并先交一次(保住 20~30 分)→ 15–40 分钟 冲第 3、4 档 → 40–50 分钟 造小数据对拍、检查 freopen 与文件名。
课堂上别让学生"从头想正解"。先要求每个人 15 分钟内交出第 1、2 档, 再放开冲正解。这个顺序一换,平均分通常能涨一大截——因为它杜绝了"想了 40 分钟,交上去 0 分"。
检测

五道题

① 5 人选正副班长,有几种?

② 1 ~ 10 中有几个素数?

③ 求 C(n,r) 时,为什么每步都要取模?

④ 线性筛里 if (i % p == 0) break; 的作用是?

椰程锦囊:检测①是本讲性价比最高的一题—— "正副班长"与"组队"只差一个词,答案差一倍,正好把"有序 vs 无序"钉死在学生脑子里。

目录