简单约数

当然是重要的图片:

max d&w

关于约数

若整数 \(n\) 除以整数 \(d\) 的余数为 \(0\),即 \(d\) 能整除 \(n\),则称 \(d\)\(n\) 的约数,记作 \(d | n\)

算数基本定理推论

在算数基本定理中:若正整数 \(N\) 被唯一分解为 \(N = p_1^{c_1} p_2^{c_2} \cdots p_m^{c_m}\),其中 \(c_i \in \mathbb{Z}, p_i \in \mathbb{P}, p_1 \lt p_2 \lt \cdots \lt p_m\),则 \(N\) 的正约数集合可写作:

\(N\) 的正约数个数为(可用乘法原理证明):

\[\prod_{i = 1}^{m} (c_i + 1) \]

\(N\) 的所有正约数之和为:

\[\prod_{i = 1}^{m} \left( \sum_{j = 0}^{c_i} (p_i)^{j} \right) \]

求正约数集合

\(N\) 的正约数集合

类似试除法:

void DivideNum(const int n) {
    if (n % i == 0) {
        fac[++m] = i;
        if (i != n / i)
            fac[++m] = n / i;
    }
}

由此我们得到一个推论:

一个整数 \(N\) 的约数个数上限为 \(2 \sqrt{N}\)

\([1, N]\) 每个数的正约数集合

如果枚举 \(1 \sim N\) 试除法变成 \(O(N \sqrt{N})\) 显然太慢了,换个思路:\(1 \sim N\) 中以 \(d\) 为约数的数就是 \(d\) 的倍数 \(1d, 2d, 3d, \dots\)

std::vector<int> fac[N];
void DivideNum(const int n) {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n / i; j++)
            fac[i * j].push_back(i);
    }
}

复杂度是调和级数 \(O(N \log N)\) 的。

由此我们可以得到一个新的推论:

\(1 \sim N\) 每个数的约数个数的总和大约为 \(N \log N\)

最大公约数、最小公倍数

不加证明地给出一些定理,证明并不困难,大多可以通过定义和同余的推论来验证:

  • \[\forall a, b \in \mathbb{N}, \gcd(a, b) \times \text{lcm}(a, b) = a \times b \]

  • 更损相减术
    • \[\forall a, b \in \mathbb{N}, a \geq b, \gcd(a, b) = \gcd(b, a - b) = \gcd(a, a - b) \]

    • \[\forall a, b \in \mathbb{N}, \gcd(2a, 2b) = 2 \gcd(a, b) \]

  • 欧几里得算法
    • \[\forall a, b \in \mathbb{N}, b \neq 0, \gcd(a, b) = \gcd(b, a \bmod b) \]

    • 复杂度是 \(O(\log(a + b))\) 的,是最常用的求解 gcd 的方法。在高精度除法中可以考虑使用更损相减术来代替欧几里得算法
posted @ 2024-11-29 19:55  revkiru  阅读(5)  评论(0编辑  收藏  举报