1 条题解
-
0
思路与算法
σ(n)对互质因子可乘。将n唯一分成递增素数幂,逐个枚举素数p及指数e,使几何和1+p+...+p^e整除剩余目标rem,再递归处理剩余素数。若rem-1是允许的更大素数,直接得到一个一次素因子结尾。预筛50000以内素数支持2e9范围试除,最后排序去重并输出全部号码。
正确性说明
唯一素因数分解使任何解对应唯一递增素数幂序列,其各几何和相乘正好为S。递归只接纳整除目标的几何和,因此生成的一定是解。若未处理素数超过sqrt(rem),指数只能1且只可能剩一个素因子,否则几何和乘积已超过rem;这由rem-1素数分支完整涵盖。
复杂度
筛表初始化O(BloglogB)、空间O(B),B=50000。设实际搜索节点V、每点试探素数幂次数合计E,试除判素最坏O(π(B)),搜索O(E+Vπ(B)),结果排序O(AlogA)。深度受不同素因子数限制,结果与递归额外空间O(A+V的最大深度)。
易错点
S=1对应n=1,σ(1)=1。无解也输出计数0及空第二行;多个输入直到EOF,输出排序且不能重复。
参考代码(C++11)
#include <bits/stdc++.h> using namespace std; vector<int> pr; bool prime(long long x) { if (x < 2) return false; for (int p : pr) { if (1LL * p * p > x) break; if (x % p == 0) return false; } return true; } vector<long long> ans; void dfs(long long rem, int at, long long value) { if (rem == 1) { ans.push_back(value); return; } if (rem - 1 >= (at < (int)pr.size() ? pr[at] : 50000) && prime(rem - 1)) ans.push_back(value * (rem - 1)); for (int i = at; i < (int)pr.size() && 1LL * pr[i] * pr[i] <= rem; i++) { long long p = pr[i], pw = p, sum = 1 + p; while (sum <= rem) { if (rem % sum == 0) dfs(rem / sum, i + 1, value * pw); pw *= p; sum += pw; } } } int main() { vector<bool> is(50001, true); for (int i = 2; i <= 50000; i++) if (is[i]) { pr.push_back(i); for (int j = i + i; j <= 50000; j += i) is[j] = false; } long long s; while (cin >> s) { ans.clear(); dfs(s, 0, 1); sort(ans.begin(), ans.end()); ans.erase(unique(ans.begin(), ans.end()), ans.end()); cout << ans.size() << '\n'; for (size_t i = 0; i < ans.size(); i++) cout << ans[i] << (i + 1 == ans.size() ? '\n' : ' '); if (ans.empty()) cout << '\n'; } }
- 1