簡體   English   中英

找出三個數是給定數的除數且它們的和最小

[英]Find three numbers that are divisors of given number and their sum is minimal

我試圖解決這個問題超過一天,但我無法找到合理的解決方案。 我認為這是一個相當簡單的編程問題,更像是一個算法問題。 我們有一個給定的數字 N, (1< N<10^9) 並且我們必須找到三個數字 M,P,Q 所以它們滿足 M×P×Q=N 並且它們的和是最小的(最小的可能)。I想出了這段代碼,但它不適用於范圍內的所有數字(例如 6)。 我試圖找到最接近 N 的第三根的最大除數。該程序適用於大多數數字,但不適用於所有數字。 我想知道 while 是否是最好的方法,或者我應該使用或其他循環。 先感謝您! 祝你有美好的一天!

PS 一些例子 - 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;
}

我發現你的想法很有趣。 首先尋找一個接近三次根的分頻器。 然后,在第二步中,尋找接近剩余平方根的除法器。

以下代碼似乎適用於您引用的案例,包括輸入 6。

我主要嘗試簡化您的代碼,刪除看起來很奇怪且似乎沒有用的代碼。 我還確保第二步是有效地嘗試搜索接近剩余平方根的因子,這有一點錯誤。

我沒有嘗試提高程序的速度。 我想第一步是測試算法的有效性。 在第二步中,正如評論中所建議的,可以使用輸入的主要因素來固定程序,同時保持相同的策略。

在這里,最壞情況下的復雜度是 O(n),這看起來已經相當不錯了。

編輯:為了稍微固定程序,我嘗試以負序循環( i--而不是i++ )。 我檢查了你提出的測試沒有區別。 但是,對於我執行的另一項測試,我獲得了收益……

對於n = 124267948 ,我現在獲得(316, 56179, 7) sum = 56502而不是(553, 4, 56179) sum = 56736

這意味着在驗證算法之前確實需要一些進一步的測試和分析。

**編輯 2:** 我對 1 和 1e6 之間的n進行了系統測試,並比較了兩個變體(i++ 和 i--)。 它們通常提供相同的結果,在其他地方其中一個或另一個更好。 需要進一步調查。

編輯 3:我進行了系統比較,采用了一個最佳方案,該方案考慮了第一個除法器 (m) 的所有可能值,然后在余數 (n/m) 的 sqrt 附近尋找一個除法器。 我知道這個最優方案通常比其他兩個更好。 例如對於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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM