[Я не пользуюсь Java регулярно. Вот решение, использующее C. Поскольку используются только элементарные понятия, практикующий специалист по Java должен иметь возможность легко его перевести.]
Поиск в сети «суммы кубов» показывает эту страницу , которая сообщает нам сумму k 3 для k из От 1 до n равно n 2 • ( n + 1) 2 / 4.
Это уравнение четвертого порядка, для которого известны решения в замкнутой форме, но мы легко видим, что для положительных значений n , n 2 • ( n + 1) 2 / 4 между n 4 / 4 и ( n + 1) 4 / 4. Тогда, если m - сумма первых n кубов, n = этаж ((4 • m ) 1 / 4 ). Итак, если у нас есть реализация pow
, которая точно округлена с использованием округления до ближайшего (вычисляемый результат является одним из двух представляемых значений, ближайших к математическому результату), мы можем найти n с floor(pow(4*m, .25))
. Если pow
не является точно округленным, то round(pow(4*m, .25))
будет обслуживать область, для которой pow
возвращает некоторый разумный результат без слишком большой ошибки. (round
работает, потому что (4 • m ) 1/4 никогда не превышает n более чем на ½. Доказательство опущено, хотя Wolfram Alpha показывает нам предел, когда n переходит в ∞, равен ½ , а избыток монотонный.)
Таким образом, если m является суммой первых n кубов, то n является результатом round(pow(4*m, .25))
. Таким образом, мы можем вычислить это значение для n , а затем вычислить сумму первых n кубов как n*n*(n+1)*(n+1)/4
и проверить, равно ли это m . Если это произойдет, мы нашли решение и вернем его. Если это не так, m не является суммой кубов, и мы возвращаем -1:
#include <math.h>
#include <stdio.h>
static double findNb(double m)
{
double n = round(pow(4*m, .25));
double sum = n * n * (n+1) * (n+1) / 4;
return m == sum ? n : -1;
}
static void Test(double m)
{
printf("findNb(%.99g) -> %.99g.\n", m, findNb(m));
}
int main(void)
{
Test(0);
Test(1);
Test(2);
Test(8);
Test(9);
Test(10);
Test(250500249999.);
Test(250500250000.);
Test(250500250001.);
}
Выход:
findNb(0) -> 0.
findNb(1) -> 1.
findNb(2) -> -1.
findNb(8) -> -1.
findNb(9) -> 2.
findNb(10) -> -1.
findNb(250500249999) -> -1.
findNb(250500250000) -> 1000.
findNb(250500250001) -> -1.
Конечно, ограничения точности с плавающей точкой приведут к сбою этого кода, если m больше, чем можно представить в double
.