给定素数列表和分解模式,如何构造其素数因子化与给定模式匹配的所有数字?

时间:2011-12-25 15:05:43

标签: c++ recursion permutation

尽管如此,我试图在标题中总结一下这个问题,但我认为如果我开始讨论这个问题的实例会更好:

Primes列表= {2 3 5 7 11 13}
分解模式= {1 1 2 1}

对于上述输入,程序应生成以下数字列表:

  • 2.3.5 ^ 2.7
  • 2.3.5 ^ 2.11
  • 2.3.5 ^ 2.13
  • 2.3.7 ^ 2.11
  • 2.3.7 ^ 2.13
  • 2.3.11 ^ 2.13
  • 2.5.7 ^ 2.11
  • 2.5.7 ^ 2.13
  • 2.7.11 ^ 2.13
  • 3.5.7 ^ 2.11
  • 3.5.7 ^ 2.13
  • 3.5.11 ^ 2.13
  • 3.7.11 ^ 2.13
  • 5.7.11 ^ 2.13

到目前为止,我理解由于模式的长度是任意大的(就像素数列表一样),我需要使用递归函数来获得所有组合。我真正的,真正困难的是 - 如何制定函数的参数/何时调用等等。这是我迄今为止开发的:

#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;

static const int factors[] = {2, 3, 5, 7, 11, 13};
vector<int> vFactors(factors, factors + sizeof(factors) / sizeof(factors[0]));
static const int powers[] = {1, 1, 2, 1};
vector<int> vPowers(powers, powers + sizeof(powers) / sizeof(powers[0]));

// currPIdx [in]  Denotes the index of Power array from which to start generating numbers
// currFidx [in]  Denotes the index of Factor array from which to start generating numbers
vector<int> getNumList(vector<int>& vPowers, vector<int>& vFactors, int currPIdx, int currFIdx)
{
    vector<int> vResult;

    if (currPIdx != vPowers.size() - 1)
    {
        for (int i = currPIdx + 1; i < vPowers.size(); ++i)
        {
            vector<int> vTempResult = getNumList(vPowers, vFactors, i, currFIdx + i);
            vResult.insert(vResult.end(), vTempResult.begin(), vTempResult.end());
        }

        int multFactor = pow((float) vFactors[currFIdx], vPowers[currPIdx]);
        for (int i = 0; i < vResult.size(); ++i)
            vResult[i] *= multFactor;
    }
    else
    {   // Terminating the recursive call
        for (int i = currFIdx; i < vFactors.size(); ++i)
        {
            int element = pow((float) vFactors[i], vPowers[currPIdx]);
            vResult.push_back(element);
        }
    }
    return vResult;
}

int main()
{
    vector<int> vNumList = getNumList(vPowers, vFactors, 0, 0);
    cout << "List of numbers: " << endl;
    for (int i = 0; i < vNumList.size(); ++i)
        cout << vNumList[i] << endl;
}

当我运行上述内容时,我的列表不正确:

List of numbers: 
66
78
650
14
22
26

我已经不知何故遇到了一个心理障碍,因为我似乎无法弄清楚如何适当地改变递归调用中的最后一个参数(我认为这是我的程序不工作的原因)!! < / p>

如果有人能够用缺少的逻辑调整我的代码(或者甚至指向我 - 我不是在寻找一个完整的解决方案!),那将是非常好的。如果你能限制你对标准C ++的回答,我将非常感激!

(如果有人注意到我错过了给定模式的排列,这会导致其他数字,如2.3.5.7 ^ 2等 - 不用担心,我打算在所有可能的排列上重复这个算法通过使用next_permutate获得给定模式!)。

PS:不是作业/面试问题,只是一个非常有趣的Project Euler问题的算法的一部分(我想你甚至可以猜出哪一个:))。

编辑:我已经自己解决了这个问题 - 我已将其作为答案发布。如果你喜欢它,那就投赞吧(我不能接受它作为答案,直到得到的票数超过其他答案!)...

2 个答案:

答案 0 :(得分:2)

暂时忘记分解。你要解决的问题是有两个列表P和F并找到P中p和f中f的所有可能配对(p,f)。这意味着你将拥有| P | * | P | -1 ... * | P | - (| F | -1)可能的配对(从P到F的第一个元素分配一个,留下| P | -1可能匹配第二个元素等)。您可能希望在代码中分离问题的这一部分。如果你以这种方式递归,最后一步是选择从P到F的最后一个元素的剩余元素。这有帮助吗?我必须承认,我不能很好地理解你的代码,以提供适合你当前状态的答案,但这就是我一般的方法。

答案 1 :(得分:1)

好吧,我自己想出了这个!这是它的代码(我希望这是不言自明的,但我可以澄清以防任何人需要更多细节):

#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;

static const int factors[] = {2, 3, 5, 7, 11, 13};
vector<int> vFactors(factors, factors + sizeof(factors) / sizeof(factors[0]));

static const int powers[] = {1, 1, 2, 1};
vector<int> vPowers(powers, powers + sizeof(powers) / sizeof(powers[0]));

// idx - The index from which the rest of the factors are to be considered. 
//       0 <= idx < Factors.size() - Powers.size()
// lvl - The lvl of the depth-first tree
//       0 <= lvl < Powers.size()
// lvlProd - The product till the previous level for that index.
void generateNumList
(  
    vector<int>& vPowers, 
    vector<int>& vFactors,
    vector<int>& vNumList, 
    int idx, 
    int lvl, 
    long lvlProd
)
{
    // Terminating case
    if (lvl == vPowers.size() - 1)
    {
        long prod = pow((float) vFactors[idx], vPowers[lvl]) * lvlProd;
        vNumList.push_back(prod);
    }
    else
    {
        // Recursive case
        long tempLvlProd = lvlProd * pow((float) vFactors[idx], vPowers[lvl]);
        for (int i = idx + 1; i < vFactors.size(); ++i)
            generateNumList(vPowers, vFactors, vNumList, i, lvl + 1, 
                            tempLvlProd);
    }
}

vector<int> getNumList(vector<int>& vPowers, vector<int>& vFactors)
{
    vector<int> vNumList;
    for (int i = 0; i < vFactors.size(); ++i)
        generateNumList(vPowers, vFactors, vNumList, i, 0, 1);
    return vNumList;
}

int main()
{
    vector<int> vNumList = getNumList(vPowers, vFactors);
    cout << endl << "List of numbers (" << vNumList.size() << ") : " << endl;
    for (int i = 0; i < vNumList.size(); ++i)
        cout << vNumList[i] << endl;
}

上面代码的输出(我必须工作很长时间才能在算法上摆脱重复的条目!):

List of numbers (15) : 
1050
1650
1950
3234
3822
9438
5390
6370
15730
22022
8085
9555
23595
33033
55055

real    0m0.002s
user    0m0.001s
sys     0m0.001s