题解:AcWing 870 约数个数
【题目来源】
AcWing:870 约数个数 - AcWing题库
【题目描述】
给定 \(n\) 个正整数 \(a_i\),请你输出这些数的乘积的约数个数,答案对 \(10^9+7\) 取模。
【输入】
第一行包含整数 \(n\)。
接下来 \(n\) 行,每行包含一个整数 \(a_i\)。
【输出】
输出一个整数,表示所给正整数的乘积的约数个数,答案需对 \(10^9+7\) 取模。
【输入样例】
3
2
6
8
【输出样例】
12
【核心思想】
-
问题分析:给定 \(n\) 个正整数 \(a_i\),求它们乘积的约数个数,答案对 \(10^9 + 7\) 取模。根据唯一分解定理,任意正整数可分解为质因数的幂次乘积;而约数个数可由各质因数指数加 \(1\) 后相乘得到。这是一个质因数分解 + 约数个数公式的数学问题。
-
算法选择:
- 试除法质因数分解:对每个 \(a_i\) 从 \(2\) 枚举到 \(\sqrt{a_i}\),逐个提取质因数并统计指数
- 哈希表统计指数:使用
unordered_map合并所有数的相同质因数,累加各自的总指数 - 约数个数公式:若乘积的质因数分解为 \(\prod p_i^{c_i}\),则约数个数为 \(\prod (c_i + 1)\)
-
关键步骤:
- 读取输入:整数 \(n\),以及 \(n\) 个正整数 \(a_i\)
- 质因数分解(对每个 \(a_i\)):
- 遍历 \(i\) 从 \(2\) 到 \(\lfloor \sqrt{a_i} \rfloor\):
- 当 \(a_i \bmod i == 0\) 时,不断除以 \(i\),同时
primes[i]++
- 当 \(a_i \bmod i == 0\) 时,不断除以 \(i\),同时
- 若分解后 \(a_i > 1\),说明剩余部分本身是一个质因数,
primes[a_i]++
- 遍历 \(i\) 从 \(2\) 到 \(\lfloor \sqrt{a_i} \rfloor\):
- 合并统计:
primes中key为质因数,value为该质因数在所有 \(a_i\) 中的总指数 - 计算约数个数:
- 初始化
ans = 1 - 遍历每个质因数 \((p, c)\):
ans = ans \times (c + 1) \bmod (10^9 + 7)
- 初始化
- 输出答案
ans
-
时间/空间复杂度:
- 时间复杂度:\(O(n \cdot \sqrt{A})\),\(A\) 为 \(a_i\) 的最大值。对每个数试除到平方根
- 空间复杂度:\(O(P)\),\(P\) 为不同质因数的个数,用哈希表存储
-
约数个数的核心思想:
- 唯一分解定理:任意正整数 \(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
浙公网安备 33010602011771号