查找三个数字为给定数的因数,并且它们的和最小

时间:2019-11-16 14:11:03

标签: c++ algorithm

我试图解决这个问题超过一天,但我无法提供合理的解决方案。我认为这是一个相当容易的编程问题,更多是算法问题。我们有一个给定的数字N(1

P.S。一些示例-100 = 4×5×5,121 = 11×11×1,8 = 2×2×2,400 = 8×5×10,1000 = 10×10×10,4000 = 16×10×25等等。

int main() {
    int m = 0, n = 0, p = 0, q = 0, i = 0;;
    std::cin >> n;
    i = int(std::cbrt(n));
    while (true) {
        int ten = std::cbrt(n);
        if (pow(ten, 3) == n) {
            m = ten;
            p = ten;
            q = ten;
            break;
        }
        int square = n;
        if (i * i == square) {
            n = i;
            m = i;
            p = i;
            break;
        }
        if (i == 1) {
            m = n;
            p = 1;
            q = 1;
            break;
        }
        if (n % i == 0) {
            n = n / i;
            m = i;
            p = n;
            break;
        }
        i++;
    }
    i = std::cbrt(n);
    while (true) {
        int ten = std::cbrt(n);
        if (pow(ten, 3) == n) {
            m = ten;
            p = ten;
            q = ten;
            break;
        }
        int square = n;
        if (i * i == square) {
            p = i;
            q = i;
            break;
        }
        if (i == 1) {
            q = 1;
            break;
        }
        if (n % i == 0) {
            q = n / i;
            p = i;
            break;
        }
        i++;
    }
    std::cout << m << " " << p << " " << q << std::endl;
    return 0;
}

1 个答案:

答案 0 :(得分:0)

我发现您的想法很有趣。首先寻找靠近立方根的分隔线。然后,在第二步中,寻找与其余平方根接近的除法器。

以下代码似乎适用于您引用的情况,包括输入6。

我主要是试图简化您的代码,删除看起来很奇怪但似乎没有用的代码。我还确保第二步是有效地尝试寻找与余数的平方根相近的因数,在此方面存在一些错误。

我没有尝试提高程序速度。我想第一步是测试算法的有效性。在第二步中,如评论中所建议,可以使用输入的主要因素来固定程序,同时保持相同的策略。

在这里,在最坏的情况下,复杂度为O(n),这似乎已经很不错了。

编辑: 为了稍微固定程序,我尝试以负顺序循环(i--而不是i++)。我检查过,对于您提出的测试没有什么区别。但是,对于我执行的另一项测试,我获得了增益...

对于n = 124267948,我现在获得(316, 56179, 7) sum = 56502而不是(553, 4, 56179) sum = 56736

这意味着在验证算法之前,确实需要进行进一步的测试和分析。

**编辑2:** 我对n在1和1e6之间进行了系统测试,并比较了两个变体(i ++和i--)。它们通常提供相同的结果,而在其他地方则更好。需要进一步调查。

修改3: 我进行了系统的比较,使用了一个最佳方案,该方案考虑了第一个除法器(m)的所有可能值,然后在其余的平方根(n / m)附近寻找一个除法器。我知道这种最佳方案通常比其他两种方案更好。例如n=44。这种最佳方案更加复杂,但是计算时间似乎很短。

#include    <iostream>
#include    <cmath>

int main() {
int m = 0, n = 0, p = 0, q = 0, i;
bool end = false;
std::cin >> n;
i = int(std::cbrt(n));
//std::cout << "cbrt(n) = " << i << "\n";

if (n == 1) {
    m = p = q = 1;
    end = true;
} else {
    if (i == 1) i = 2;
    if (pow(i, 3) == n) {
         m = i;
         p = i;
         q = i;
         end = true;    
    }
}

if (!end) {

//  1st step: research of a factor almost equal to a cubic root
    i++;
    while (true) {
        if (n % i == 0) {
            n = n / i;
            m = i;
            break;
        }
        i--;
    }

 // 2nd step: research of factor almost equal to the sqrt 
    i = std::sqrt(n) + 1;

    //std::cout << "before square search: n = " << n  << "\ti = " << i << "\n";
    while (!end) {  
        if (n % i == 0) {
            p = i;
            q = n/i;
            end = true;
        }
        i--;
    }
}

    std::cout << m << " " << p << " " << q << std::endl;
    return 0;
}