约数个数 & 约数之和
c++
约数个数 & 约数之和
/* * * 约数个数 & 约数之和 * * 问题描述: * 给定数字 x,问数字 x 的约数个数和约数求和的结果。 * * 算法思路1: * 最朴素的做法,使用试除法求出 `x` 的所有约数,那么个数以及约数和就可以得到。 * 复杂度 O(\sqrt(N)) * 算法思路2: * 算术基本定理: * 又称为自然数唯一分解定理,任一大于1的自然数都可分解成若干质因数的连乘积,如果不计各质因数的顺序,这种分解是唯一的。 * 我们假设 x 可以表示为 * $x=p_1^{a_1} p_2^{a_2} ... p_k^{a_k}$,其中 $p_1 \le p_2 \le \cdots \le p_k, 任意i \in[1,k], a_i \ge 1$ * p_1, p_2, ..., p_k 组成了 x 的质因数集合。 * 那么由算数基本定理可得: * num_divisors = (a_1 + 1) (a_2 + 1) ... (a_n + 1) ------------- 公式(1) * sum_divisors = (1 + p_1 + p_1^2 + ... + p_1^{a_1}) (1 + p_2 + p_2^2 + ... + p_2^{a_1}) * ... (1 + p_k + p_k^2 + ... + p_k^{a_k}) ------------- 公式(2) * 其中约数的数量完全可以排列组合得到,约数求和恰好可以由公式(2)拆解得到 * 复杂难度仅仅在找质因数上。复杂度 O(\sqrt(N)),但是和算法思路1不同,这是最坏复杂度,基本上是不会达到O(\sqrt(N))的。 */ #include <cstdio> #include <cstring> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <unordered_map> using namespace std; typedef pair<int, int> PII; typedef long long LL; const int MOD = 1e9 + 7; int n; vector<PII> prime_divisors; unordered_map<int, int> prime_to_idx; void get_prime_divisors(int x) { int cnt = 0, cur; for (int i = 2; i <= x / i; i ++ ) { if (x % i == 0) { cnt = 0; while (x % i == 0) { x /= i; cnt += 1; } if (prime_to_idx.count(i) == 0) { prime_to_idx[i] = prime_divisors.size(); prime_divisors.push_back(PII(i, 0)); } cur = prime_to_idx[i]; prime_divisors[cur].second += cnt; } } if (x != 1) { if (prime_to_idx.count(x) == 0) { prime_to_idx[x] = prime_divisors.size(); prime_divisors.push_back(PII(x, 0)); } cur = prime_to_idx[x]; prime_divisors[cur].second += 1; } } LL get(int a, int b) { LL sum = 1; for (int i = 1; i <= b; i ++ ) { sum = (sum * a + 1) % MOD; } // printf("%d %d %lld\n", a, b, sum); return sum; } LL get_divisor_sum(vector<PII> prime_divisors) { LL res = 1ll; for (int i = 0; i < prime_divisors.size(); i ++ ) { res = res * get(prime_divisors[i].first, prime_divisors[i].second) % MOD; } return res; } LL get_divisor_num(vector<PII> prime_divisors) { LL res = 1ll; for (int i = 0; i < prime_divisors.size(); i ++ ) { res = res * (prime_divisors[i].second + 1) % MOD; } return res; } void show() { printf("***********************\n"); for (int i = 0; i < prime_divisors.size(); i ++ ) { printf("%d %d\n", prime_divisors[i].first, prime_divisors[i].second); } printf("***********************\n"); } int main() { scanf("%d", &n); int x; while(n -- ) { scanf("%d", &x); get_prime_divisors(x); } // show(); printf("%lld\n", get_divisor_sum(prime_divisors)); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)