[英]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.