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

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


搜索

LOJ 10020 - 小木棍

  • 满足 $nm = \sum a_i = N$, 则需要满足 $N \mod n = 0$。
  • 较劣方案:使用 DFS 一根一根构造木棍。
  • 代码实现注意细节。
#include <bits/stdc++.h>
using namespace std;

const int N = 70;
int n, a[N], L;
bool vis[N], flag;

void dfs(int s) {  // s - 当前木棍长度
    bool ok = 0;
    for (int i = 1; i <= n; ++i)
        if (!vis[i]) ok = false;
    if (ok) return flag = true, void();
    for (int i = 1; i <= n; ++i)
        if (!vis[i] && s + a[i] <= L) {
            vis[i] = 1;
            s += a[i];
            if (s == L) s = 0;
            dfs(s);
            if (!s) s = L;
            s -= a[i];
            vis[i] = false;
            if (flag) return;
        }
}

int main() {
    // read.
    sort(a + 1, a + n + 1);
    reverse(a + 1, a + n + 1);
    int sum = 0;
    for (int i = 1; i <= n; ++i) sum += a[i];
    for (int i = a[1]; i <= sum; ++i) if (!(sum % i)) {
        L = i;
        flag = false;
        dfs(0);
        if (flag) return cout << i << '\n', 0;
    } return 0;
}
  • 搜索优化思路:减少状态数、减少状态处理时间(较难)。

分治

逆序对

  • 使用归并排序。
  • 思考题:对有序数列随机交换 $k$ 次,求逆序对的期望个数。

    • 归并排序。

贪心

  • 局部最优解 = 全局最优解。
  • 反例:背包问题,局部最优解 $\ne$ 全局最优解。

Example

有 $n$ 个怪物,每个怪物有攻击力 $a_i$ 和 $b_i$,每一轮可以对一个怪物造成 $1$ 的伤害,每个怪物会对你造成 $a_i$ 的伤害,求你受到伤害最小的攻击顺序,$n \le 10^5$。

  • 优先打 $\frac{a_i}{b_i}$ (攻血比)较高的。
  • 如何证明?

    • 考虑反证法。
    • 如果先打攻血比较低的,受到的伤害一定不小于先打攻血比高的。
    • 如果 $\frac{a_i}{b_i} < \frac{a_{i + 1}}{b_{i + 1}}$,则原受到 $b_i(a_i + a_{i + 1}) + b_{i + 1}a_{i + 1}$ 的伤害,交换后受到 $b_{i + 1}(a_i + a_{i + 1}) + b_i a_i$,整理后得到 $a_{i + 1} b_i$ 和 $a_i b_{i + 1}$,则有 $a_{i + 1} b_i > a_i b_{i + 1}$。

快速幂

  • 任意满足结合律的都可以使用快速幂。
  • 递归实现:
ll qpow(ll a, ll b) {
    if (!b) return 1;
    ll res = qpow(a, b >> 1);
    res = res * res % p;
    if (b & 1) res = res * a % p
    return res;
}
  • 循环实现:
ll qpow(ll a, ll b) {
    ll res = 1;
    while (b) {
        if (b & 1) res = res * a % p;
        a = a * a % p, b >>= 1;
    } return res;
}

龟速乘 / 快速乘

ll mul(ll a, ll b) {
    if (!b) return 1;
    ll res = 0;
    whlie (b) {
        if (b & 1) res = (res + a) % p;
        a = (a + a) % p, b >>= 1;
    } return res;
}

矩阵快速幂

  • 有结合律,但无交换律。
  • 可用于求较大的递推。

Example. 求斐波那契数列在模 $p$ 意义下的第 $n$ 项。

ST表

  • 用于处理 RMQ 问题。

Example

给定一个序列,询问区间最小值,$n \le 10^5$,$q \le 10^7$。

  • 要做到 $O(1)$ 询问,则预处理出 $f_{i,j}=\min_{k\in[i,i+2^i)} a_k$。

LCA

Tarjan.

  • 记录每个点的深度。
  • 先把较低点抬高,使得两点位于同一深度。
最后修改:2024 年 02 月 14 日
如果觉得我的文章对你有用,请随意赞赏