更佳的阅读体验:2023 国庆集训 Day 6B 笔记,本文同步发表于 洛谷博客

以下内容为个人总结,如有错误或您有不同见解,欢迎指出。


矩阵

矩阵的运算

加 / 减法

  • 两个 一样大 的矩阵,对应位置相加 / 减。

乘法

  • 要求 $n \times m$ 的矩阵与 $m \times k$ 的矩阵相乘,即第一个矩阵的列数等于第二个矩阵的行数。
  • 结果是一个 $n \times k$ 的矩阵,即行数等于第一个矩阵的行数,列数等于第二个矩阵的列数。

$$ \left[\begin{matrix} 1 & 2 \\ 3 & 4 \end{matrix}\right] \times \left[\begin{matrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{matrix}\right] = \left[\begin{matrix} 9 & 12 & 15 \\ 19 & 26 & 33 \end{matrix}\right] $$

struct matrix {
    int n, m;  // 矩阵的行数 列数
    int a[20][20];  // a[i][j] 代表矩阵第 i 行第 j 列
    matrix() {  // 构造函数
        n = m = 0;
        memset(a, 0, sizeof(a));
    }
};

matrix operator*(const matrix &m1, const matrix &m2) {  // 计算 m1 * m2, O(n^3)
    matrix m3;  // 结果矩阵
    m3.n = m1.n, m3.m = m2.m;
    for (int i = 1; i <= m3.n; ++i)
        for (int j = 1; j <= m3.m; ++j)  // 计算结果矩阵中第 i 行第 j 列的数
            for (int k = 1; k <= m1.m; ++k)
                m3.a[i][j] += m1.a[i][k] * m2.a[k][j];
    return m3;
}

矩阵快速幂

求矩阵 $x$ 的 $y$ 次方。

  • 单位矩阵:主对角线为 $1$ 其余为 $0$ 的矩阵 $I = \left[\begin{matrix} 1 & 0 & 0 & \cdots & 0 \\ 0 & 1 & 0 & \cdots & 0 \\ 0 & 0 & 1 & \cdots & 0 \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & 0 & \cdots & 1 \end{matrix}\right]$。
matrix qpow(const matrix x, int y) {  // 计算 x 的 y 次方
    matrix ans;
    ans.n = ans.m = x.n;
    for (int i = 1; i <= x.n; ++i) ans.a[i][i] = 1;
    while (y) {
        if (y & 1) ans = ans * x;
        x = x * x, y >>= 1;
    } return ans;
}

洛谷 P1962 - 斐波那契数列

  • 构造一个矩阵 $\left[\begin{matrix} f_i & f_{i - 1} \end{matrix}\right]$​ 和 $\left[\begin{matrix}1 & 1 \\ 1 & 0\end{matrix}\right]$,可得:

$$ \left[\begin{matrix} f_1 & f_0 \end{matrix}\right] \times \left[\begin{matrix} 1 & 1 \\ 1 & 0 \end{matrix}\right] ^n = \left[\begin{matrix} f_{n + 1} & f_n \end{matrix}\right] $$

  • 使用矩阵快速幂求解,时间复杂度 $O(\log n)$。

递推矩阵

$$ \left[\begin{matrix} a_i & a_{i - 1} & a_{i - 2} \end{matrix}\right] \times \left[\begin{matrix} \cdot & \cdot & \cdot \\ \cdot & \cdot & \cdot \\ \cdot & \cdot & \cdot \end{matrix}\right] = \left[\begin{matrix} a_{i + 1} & a_i & a_{i - 1} \end{matrix}\right] $$

BZOJ #2396. 神奇的矩阵

  • 对于 $N \le 10^3$,直接矩阵乘法显然会超时。
  • 对于矩阵 $A$,$B$,$C$,直接进行 $A \times B = C$ 会达到 $O(n^3)$。
  • 考虑构造一个 $1 \times n$ 的矩阵 $D$,计算 $D \times A \times B = D \times C$,每次乘法都是 $1 \times n$ 的矩阵,时间复杂度 $O(n^2)$。
  • 随机一个 $D$,与 $A \times B$ 和 $C$ 相乘并进行比较,显然正确率非常高。

逆元

  • 用于模意义下的除法。
  • 费马小定理:当 $p$ 是质数,如果有 $a$ 满足 $\gcd(a, p) = 1$,则有 $a^{p - 1} \equiv 1 (\mod p)$。
  • 对上述同余式两边同时除以 $a$,得到 $a^{p - 2} \equiv a^{-1} (\mod p)$,即模 $p$ 意义下 $a^{p - 2}$ 与 $a^{-1}$ 相同。
  • 所以,$a$ 在模 $p$ 意义下的逆元为 $a^{p - 2}$。

组合数学

  • $C(n, m)$ 表示从 $n$ 个数中选择 $m$ 个 不同顺序算一种方案 的总方案数。

$$ C(n, m) = \frac{n(n - 1)(n - 2) \cdots (n - m + 1)}{m!} = \frac{n!}{m!(n - m)!} $$

性质

  • 组合数的递推式:$C(n, m) = C(n - 1, m - 1) + C(n - 1, m)$。
  • 从以上递推式可以得到杨辉三角,则左对齐的杨辉三角上第 $i$ 行第 $j$ 列的数即为 $C(i, j)$。

Example

给定三个数 $n$,$m$,$p$,求 $C(n, m) \mod p$。

Subtask 1: $n, m \le 1000$

  • 递推预处理杨辉三角。
int c[N][N];
for (int i = 0; i <= n; ++i) {
    c[i][0] = 1;
    for (int j = 1; j <= i; ++j)
        c[i][j] = c[i - 1][j - 1] + c[i - 1][j] % p;
}

Subtask 2: $n, m \le 10^6$,$p \approx 10^9$,且 $p$ 是质数

  • 预处理阶乘以及阶乘的逆元。
int fac[N], ifac[N];  // fac[i] 代表 i! % p, ifac[i] 代表 1 / i! % p

fac[0] = 1;
for (int i = 1; i < N; ++i)
    fac[i] = 1ll * fac[i - 1] * i % p;
for (int i = 0; i < N; ++i)
    ifac[i] = qpow(fac[i], p - 2);

int C(int n, int m) {  // 求 C(n, m) % p, C(n, m) = n! / m! / (n - m)!
    return 1ll * fac[n] * ifac[m] % p * ifac[n - m] % p;
}

Subtask 3: $n \le 10^9, m \le 10^3, p \le 10^9$,$p$ 不保证是质数

  • 使用公式 $C(n, m) = \frac{n(n - 1)(n - 2) \cdots (n - m + 1)}{m!}$。
  • 因为结果一定是整数,则分子一定是分母的倍数。
  • 求 GCD。
int fenzi[N], fenmu[N];  // 分子,分母

int C(int n, int m) {
    for (int i = 1; i <= m; ++i) {
        fenzi[i] = n - i + 1;
        fenmu[i] = i;
    } for (int i = 1; i <= m; ++i)
        for (int j = 1; j <= m; ++j) {
            int g = __gcd(fenzi[i], fenmu[j]);
            fenzi[i] /= g, fenmu[j] /= g;
        }
    int ans = 1;
    for (int i = 1; i <= m; ++i)
        ans = 1ll * ans * fenzi[i] % p;
    return ans;
}

概率和期望

加法原理与乘法原理

加法原理与乘法原理

  • 加法原理:同阶段互斥;
    乘法阶段:不用阶段不互斥。

条件概率

  • 已知事件 $B$ 发生时事件 $A$ 发生的概率 $P(A|B)$。

Example 1

假设有 $3$ 张形状相同的卡片,其中一张两面都是黑色,一张两面都是红色,另一张是一面红一面黑,随机取出一张放在桌上,朝上的面为红色,那么另一面是黑色的概率是多少?

  • 得到答案 $\frac{1}{3}$。

Example 2

$n$ 个人按任意顺序一次抓阄,每个人抓完阄后立即打开,当某个人抓到「中」时,整个抓阄过程结束(后面的人就不必抓了)。问:此种抓阄方式是否公平,请说明理由。

  • 每个人的概率都是 $\frac{1}{n}$,公平。

Example 3

在小葱和小泽面前有三瓶药,其中有两瓶是毒药,每个人必须喝一瓶。小葱和小泽各自选了一瓶药,小泽手速比较快,将药喝了下去,然后就挂掉了。小葱想活下去,它是应该喝掉手上的这瓶,还是另外剩下的一瓶呢?

  • 无论是否更换手上的药水,小葱挂掉的概率为 $50 \%$,则换与不换答案不变。

Example 4

小葱想要过河,有两条路:

  • 一条路有 $100$ 个石头,每个石头有 $\frac{1}{100}$ 的概率会挂掉。
  • 另一条路有 $1000$ 个石头,每个石头有 $\frac{1}{1000}$ 的概率会挂掉。

小葱应该走哪边呢?(请勿使用计算器)

  • 走第一条路活下来的概率为 $(\frac{99}{100})^{100}$,走第二条路活下来的概率为 $(\frac{999}{1000})^{1000}$。
  • 整理并约分后得到 $(\frac{99}{100})^{100} < (\frac{999}{1000})^{1000}$,所以应该走第二条路。

Example 5

小泽在数轴上的点 $0$ 处。

小泽每次有 $r$ 的概率向右走,有 $1 - r$ 的概率向左走,问小泽走到 $-1$ 的概率。

  • 令答案为 $p$,得到 $p = (1 - r) + rp^2$,解得 $p = \frac{1 - r}{r}$。
  • 思考当 $r < \frac{1}{2}$ 时 $p$ 的值。此时应有 $p = 1$。

期望

  • $\sum$ 每一种情况的权值 $\times$ 这种情况的概率。
  • 和的期望等于期望的和:$E(X_1 + X_2) = E(X_1) + E(X_2)$。

BZOJ #2969. 矩形粉刷

  • 令第 $i$ 行第 $j$ 列的格子为 $x_{i, j}$,$x_{i, j} = 0$ 时表示这个格子没有被刷,$x_{i, j} = 1$ 表示这个格子已经被刷。
  • 令 $X=被刷格子数量$,得到 $E(X) = E(x_{1,1} + x_{1, 2} + \cdots + E_{n, m})$。
  • 令 $p_{i, j}$ 为第 $i$ 行第 $j$ 列的格子被刷过的概率,则 $E(X) = \sum p_{i, j}$。
  • 总情况数为 $n^2m^2$,能刷掉 $(i, j)$ 的方案数为 $i(n - i + 1) \cdot j(m - j + 1)$,则只刷一次刷掉 $(i, j)$ 的概率 $q_{i, j} = \frac{i(n - i + 1) \cdot j(m - j + 1)}{n^2m^2}$,一次刷不掉的概率为 $1 - q_{i, j}$,$k$ 次刷不掉的概率为 $(1 - q_{i, j})$。
  • 得到 $p_{i, j} = 1 - (1 - q_{i, j})^k$,所以 $E(X) = \sum p_{i, j} = \sum [1 - (\frac{i(n - i + 1) \cdot j(m - j + 1)}{n^2m^2})^k]$。
最后修改:2024 年 02 月 14 日
如果觉得我的文章对你有用,请随意赞赏