【问题标题】:given prime factorization of a number iterate through all factors in c++ without recursion给定一个数的素数分解迭代C++中的所有因子而不递归
【发布时间】:2016-12-28 21:50:15
【问题描述】:

我得到一个数字 p1^x1 * p2^x2 * .... 在地图中的素数分解。 我需要遍历它的所有因子,素数和复合因子。 我设法使用递归编写了一个解决方案。

#include <iostream>
#include <map>
#include <cstdlib>

using namespace std;

struct PROBLEM {

    int mx = 400;
    map<int, int> mp = {{2, 2}, {3, 1},  {5, 1}, {7, 2}};
    int lastPrimeFactor = 7;
    int num = 1;

    auto solve() {
        rec(2, 0);
        return 0;
    }

    int next_prime_factor(int p) {
        return (p == 2) ? 3 : (p == 3) ? 5 : (p == 5) ? 7 : -1;
    }

    void rec(int prime, int power) {

        if (mx == 0) {
            cout << "Infinite recursion\n\n";
            exit(0);
        } else --mx;

        if (prime == lastPrimeFactor && power > mp[prime]) {
            return;
        }

        if (power < mp[prime]) {
            num *= prime;
            cout << num << endl;
            rec(prime,  power + 1);
            num /= prime;
        }

        if (prime != lastPrimeFactor) {
            rec(next_prime_factor(prime),  0);
        }

    }

};


int main() {
    PROBLEM().solve();
    return 0;
}

问题:

1) 有没有更快的方法来生成这些因子?

2)如果可能的话,我可以用while循环替换递归吗?

【问题讨论】:

标签: c++ math recursion primes number-theory


【解决方案1】:
  1. 。您的递归算法与除数的数量完全相同。任何渐近速度更快的算法都无法打印所有这些数字。

  2. 是的。任何递归算法都可以使用std::stack 以非递归方式重写以存储局部变量。但是,在您的情况下,这可能不会更快,并且会使代码的可读性大大降低,因此这种重写是不可取的。如有需要,我可以为您提供代码。

【讨论】:

  • 谢谢。那么我将保留递归方法。我想我只需要在 power
【解决方案2】:

如果没有递归,它可能看起来像:

bool increase(const std::vector<std::pair<std::size_t, std::size_t>>& v,
              std::vector<std::size_t>& it)
{
    for (std::size_t i = 0, size = it.size(); i != size; ++i) {
        const std::size_t index = size - 1 - i;
        ++it[index];
        if (it[index] > v[index].second) {
            it[index] = 0;
        } else {
            return true;
        }
    }
    return false;
}

std::size_t pow(std::size_t n, std::size_t power)
{
    std::size_t res = 1;
    for (std::size_t i = 0; i != power; ++i) {
        res *= n;
    }
    return res;
}

void do_job(const std::vector<std::pair<std::size_t, std::size_t>>& v,
            std::vector<std::size_t> it)
{
    std::size_t res = 1;
    for (std::size_t i = 0; i != v.size(); ++i) {
        res *= pow(v[i].first, it[i]);         
    }
    std::cout << res << std::endl; 
}

void iterate(const std::vector<std::pair<std::size_t, std::size_t>>& v)
{
    std::vector<std::size_t> it(v.size(), 0);

    do {
        do_job(v, it);
    } while (increase(v, it));
}

Demo

所以基本上,我们{0, 0, 0, 0}{2, 1, 1, 2}

【讨论】:

  • 啊..!很好。这就像我之前编写过的 next_permutation 一样。谢谢!
猜你喜欢
  • 2011-04-08
  • 2017-11-12
  • 1970-01-01
  • 2016-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多