Ответ 1
Так как это проблема Project Euler, вы должны иметь возможность сделать это примерно за минуту вычислительного времени на современном компьютере. Они не всегда придерживаются этого, но это указывает на то, что время работы k*n^2
или k*n^2*log(n)
, вероятно, отлично, если константа не так уж плоха, но, вероятно, не k*n^2.5
или k*n^3
.
Как прокомментировал SleuthEye, сторона c должна быть четной, иначе внутренняя часть квадратного корня должна быть нечетной, поэтому взятие квадратного корня и деление на 2 не могли бы сделать целое число.
Вы можете упростить уравнение до 4(mc^2+(c/2)^2) = 2(a^2+b^2)
.
Вот один из подходов: Создайте два словаря, слева и справа. Для каждого, пусть ключи являются возможными значениями этой стороны уравнения, и пусть значения представляют собой список пар (mc,c/2)
или (a,b)
, которые производят ключ. Для правильного словаря нам нужно только рассмотреть, где a
и b
имеют одинаковую четность и где 1<=a<=b<=n
. Для левой стороны нам нужно только рассмотреть 1<=c/2<=n/2
и 1<=mc<=sqrt(3)/2 n
, так как 4mc^2 = 2a^2+2b^2-c^2 <= 3b^2 <=3n^2
.
Затем просмотрите возможные ключи и сравните элементы значений из каждого словаря, найдя число совместимых пар ((mc,c/2),(a,b))
, где b <= c < a+b
. Этот внутренний шаг не является постоянным, но максимальная и средняя длины списков не слишком велики. Способы записи n в виде суммы двух квадратов примерно соответствуют (вплоть до единиц) способам смены n в гауссовских целых числах и точно так же, как наибольшее число факторов целого числа не растет слишком быстро, то же самое верно и в гауссовских целых числах. Этот шаг занимает O(n^epsilon)
время для любого epsilon>0
. Таким образом, общее время работы O(n^(2+epsilon))
для любого epsilon>0
.
На практике, если у вас закончилась нехватка памяти, вы можете создать частичные словари, где ключи ограничены в определенных диапазонах. Это тоже хорошо распараллеливается.