1 条题解

  • 0
    @ 2026-10-26 15:31:29

    思路与算法

    σ(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

    信息

    ID
    1800
    时间
    1000ms
    内存
    512MiB
    难度
    普及+
    标签
    递交数
    1
    已通过
    1
    上传者