zoukankan      html  css  js  c++  java
  • bzoj 3629

    给出数 $n$
    记 $f(x)$ 表示 $x$ 的因子和
    求出所有 $x$ 使得 $f(x) = n$
    考虑 $x = p_1 ^{a_1} * p_2 ^ {a_2} * cdots * p_k ^ {a_k}$
    那么 $f(x) = (1 + p_1 + p_1 ^ 2 + cdots + p_1 ^ {a_1}) * (1 + p_2 + p_2 ^ 2 + cdots + p_2 ^ {a_2}) * cdots * (1 + p_k + p_k
    ^ 2 + cdots + p_k ^ {a_k})$
    因此可以爆搜枚举 $p, a$
    Dfs(Now_result, prime_pos, x_remind) {}
    分别表示
    1.当前结果,即枚举到的素数的指数次幂的乘积,即 $p_i ^ {a_i}$ 的乘积 
    2.当前枚举到的素数位置 首先要求出 $1e5, sqrt(limit)$ 内的素数
    3.给出的 $x$ 在枚举了之前的数后还剩多少
    对于答案的录入
    1.如果 x_remind = 1 ,相当于枚举到了这样一种形式 $() * () * () * p_i ^ 0$, 显然当前 Now_result 可以录入.
    2.如果 x_remind - 1 是一个 大于等于 Prime[Prime_pos] 的素数,显然 (x_remind - 1) * Now_result 可以录入.
    考虑这样的话我们已经枚举到了这样的一种形式 $() * () * () * (p_i + 1)$, 所以还原之前的数就是 p_i * Now_result.

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    
    using namespace std;
    
    #define gc getchar()
    
    inline int read() {
        int x = 0; char c = gc;
        while(c < '0' || c > '9') c = gc;
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
        return x;
    }
    
    const int N = 1e5 + 10;
    
    #define LL long long
    
    LL Prime[N], Mark[N], Ans_js;
    LL Answer[N], tot, n;
    
    void Get_prime() {
        for(int i = 2; i <= N - 5; i ++) {
            if(!Mark[i]) Prime[++ tot] = i;
            for(int j = 1; j <= tot && Prime[j] * i < N; j ++) {
                Mark[Prime[j] * i] = 1;
                if(i % Prime[j] == 0) break;
            }
        }
    }
    
    bool Is_prime(LL x) {
        if(x == 1) return 0;
        for(int i = 1; Prime[i] * Prime[i] <= x; i ++) {
            if(x % Prime[i] == 0) return 0;
        }
        return 1;
    }
    
    void Dfs(LL Now_result, int prime_pos, LL x_remind) {
        if(x_remind == 1) {
            Answer[++ Ans_js] = Now_result;
            return ;
        }
        if(x_remind - 1 >= Prime[prime_pos] && Is_prime(x_remind - 1)) {
            Answer[++ Ans_js] = (x_remind - 1) * Now_result;    
        }
        for(int i = prime_pos; Prime[i] * Prime[i] <= x_remind; i ++) {
            for(LL tmp = Prime[i] + 1, imp = Prime[i]; tmp <= x_remind; imp *= Prime[i], tmp += imp) {
                if(x_remind % tmp == 0) Dfs(Now_result * imp, i + 1, x_remind / tmp);    
            }    
        }
    }
    
    int main() {
        Get_prime();
        while(scanf("%lld", &n) == 1) {
            Ans_js = 0;
            Dfs(1, 1, n);
            sort(Answer + 1, Answer + Ans_js + 1);
            cout << Ans_js << "
    ";
            for(int i = 1; i < Ans_js; i ++) cout << Answer[i] << " ";
            if(Ans_js) cout << Answer[Ans_js] << "
    ";
        }
        return 0;
    }
  • 相关阅读:
    数组中重复的数字-剑指Offer
    不用加减乘除做加法-剑指Offer
    扑克牌顺子-剑指Offer
    左旋转字符串-剑指Offer
    翻转单词顺序列-剑指Offer
    和为S的连续正数序列-剑指Offer
    和为S的两个数字-剑指Offer
    数组中只出现一次的数字-剑指Offer
    平衡二叉树-剑指Offer
    二叉树的深度-剑指Offer
  • 原文地址:https://www.cnblogs.com/shandongs1/p/9501913.html
Copyright © 2011-2022 走看看