题解:AcWing 870 约数个数

【题目来源】

AcWing:870 约数个数 - AcWing题库

【题目描述】

给定 \(n\) 个正整数 \(a_i\),请你输出这些数的乘积的约数个数,答案对 \(10^9+7\) 取模。

【输入】

第一行包含整数 \(n\)

接下来 \(n\) 行,每行包含一个整数 \(a_i\)

【输出】

输出一个整数,表示所给正整数的乘积的约数个数,答案需对 \(10^9+7\) 取模。

【输入样例】

3
2
6
8

【输出样例】

12

【核心思想】

  1. 问题分析:给定 \(n\) 个正整数 \(a_i\),求它们乘积的约数个数,答案对 \(10^9 + 7\) 取模。根据唯一分解定理,任意正整数可分解为质因数的幂次乘积;而约数个数可由各质因数指数加 \(1\) 后相乘得到。这是一个质因数分解 + 约数个数公式的数学问题。

  2. 算法选择

    • 试除法质因数分解:对每个 \(a_i\)\(2\) 枚举到 \(\sqrt{a_i}\),逐个提取质因数并统计指数
    • 哈希表统计指数:使用 unordered_map 合并所有数的相同质因数,累加各自的总指数
    • 约数个数公式:若乘积的质因数分解为 \(\prod p_i^{c_i}\),则约数个数为 \(\prod (c_i + 1)\)
  3. 关键步骤

    • 读取输入:整数 \(n\),以及 \(n\) 个正整数 \(a_i\)
    • 质因数分解(对每个 \(a_i\)):
      • 遍历 \(i\)\(2\)\(\lfloor \sqrt{a_i} \rfloor\)
        • \(a_i \bmod i == 0\) 时,不断除以 \(i\),同时 primes[i]++
      • 若分解后 \(a_i > 1\),说明剩余部分本身是一个质因数,primes[a_i]++
    • 合并统计primeskey 为质因数,value 为该质因数在所有 \(a_i\) 中的总指数
    • 计算约数个数
      • 初始化 ans = 1
      • 遍历每个质因数 \((p, c)\)ans = ans \times (c + 1) \bmod (10^9 + 7)
    • 输出答案 ans
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n \cdot \sqrt{A})\)\(A\)\(a_i\) 的最大值。对每个数试除到平方根
    • 空间复杂度:\(O(P)\)\(P\) 为不同质因数的个数,用哈希表存储
  5. 约数个数的核心思想

    • 唯一分解定理:任意正整数 \(N = p_1^{a_1} p_2^{a_2} \cdots p_k^{a_k}\),其中 \(p_i\) 为质数,\(a_i\) 为正整数指数
    • 约数个数公式\(N\) 的约数个数 \(d(N) = (a_1 + 1)(a_2 + 1) \cdots (a_k + 1)\)。原理:每个约数对每个质因数 \(p_i\) 可选择指数为 \(0\)\(a_i\),共 \(a_i + 1\) 种选择,由乘法原理相乘得到总数
    • 跨数合并:多个数的乘积的质因数分解等于各自质因数分解的指数相加,因此可以用哈希表累加各质因数的总指数
    • 模运算处理:结果可能极大,每一步乘法都对 \(10^9 + 7\) 取模
    • 适用于乘积约数个数、GCD/LCM 相关组合计数等问题

【解题思路】

【算法标签】

约数

【代码详解】

#include <bits/stdc++.h>
using namespace std;

const int N = 105, mod = 1e9 + 7; // 定义常量 N 和 mod
unordered_map<int, int> primes; // primes 用于存储质因数及其指数
int n, a; // n 表示输入的数的个数,a 表示当前输入的数

int main()
{
    cin >> n; // 输入数的个数 n
    while (n--) { // 遍历每个数
        cin >> a; // 输入当前数 a
        for (int i = 2; i <= a / i; i++) { // 遍历 2 到 sqrt(a) 的所有整数
            while (a % i == 0) { // 如果 i 是 a 的质因数
                a /= i; // 将 a 除以 i
                primes[i]++; // 增加质因数 i 的指数
            }
        }
        if (a > 1) primes[a]++; // 如果 a 大于 1,说明 a 本身是质数
    }

    long long ans = 1; // 初始化结果为 1
    for (auto p : primes) ans = ans * (p.second + 1) % mod; // 计算约数的个数
    cout << ans << endl; // 输出结果
    return 0; // 程序结束
}
#include <bits/stdc++.h>
using namespace std;

#define int long long  // 将int定义为long long类型,防止溢出
const int mod = 1e9 + 7;  // 模数,用于取模运算

signed main()  // 因为使用了#define int long long,所以用signed main
{
    int n;  // 数字的个数
    cin >> n;

    // 使用哈希表存储质因数及其指数
    // key: 质因数
    // value: 该质因数的总指数
    unordered_map<int, int> primes;

    // 处理每个数字
    while (n--)
    {
        int x;
        cin >> x;

        // 对x进行质因数分解
        for (int i = 2; i <= x / i; i++)  // 只检查到√x
        {
            if (x % i == 0)  // 如果i是x的质因数
            {
                // 计算质因数i的指数
                while (x % i == 0)
                {
                    x /= i;           // 除以质因数i
                    primes[i]++;      // 质因数i的指数加1
                }
            }
        }

        // 如果最后x>1,那么x本身是一个质因数
        if (x > 1)
        {
            primes[x]++;  // 将剩余的质因数加入哈希表
        }
    }

    int res = 1;  // 最终结果,初始化为1

    // 根据约数个数公式计算结果
    // 公式:d(n) = ∏(a_i + 1)
    for (auto prime : primes)
    {
        // prime.first: 质因数p
        // prime.second: 指数a
        // 累乘 (a + 1) 并取模
        res = res * (prime.second + 1) % mod;
    }

    cout << res << endl;  // 输出结果

    return 0;
}

【运行结果】

5
47
45
93
3
12
144
posted @ 2026-06-21 11:24  团爸讲算法  阅读(8)  评论(0)    收藏  举报