Найти - Пользователи
Полная версия: Теорема Лагранжа
Начало » Python для новичков » Теорема Лагранжа
1 2
Comandante4
Согласно теореме Лагранжа любое натуральное число можно представить в виде суммы четырех точных квадратов. По данному числу n найдите такое представление: напечатайте от 1 до 4 натуральных чисел, квадраты которых дают в сумме данное число.
Реализовал задание следующим образом:
 def lagr(n):
    t = []
    for a in range(n, -1, -1):
        for b in range(n, -1, -1):
            for c in range(n, -1, -1):
                for d in range(n, -1, -1):
                    if a ** 2 + b ** 2 + c ** 2 + d ** 2 == n:
                        t = t + [a, b, c, d]
                        s = [x for x in t if x != 0]
                        return s
n = int(input())
print(*lagr(n), end='')
Подскажите, пожалуйста, можно ли это сделать более оптимально? Например, можно ли избежать создания списка для вывода ненулевых значений a, b, c, d? Или, может, можно избежать использование 4-х for?
Slow
ну хотя бы от int(sqrt(n)) итерируйтесь, иначе совсем тупо выходит.

а вообще вам нужно найти все разложения или любое?

если все, то вот вам в помощь - https://en.wikipedia.org/wiki/Jacobi%27s_four-square_theorem
py.user.next
Comandante4
Подскажите, пожалуйста, можно ли это сделать более оптимально?
Надо взять корень числа. Потом от этого корня взять целую часть, возвести её в квадрат и вычесть из числа. Для остатка проделать всё то же самое. Так максимум за четыре шага ты найдёшь все числа.
PEHDOM
Comandante4ну начнем с того что вы неправильно интерпретируете теорему.
Теорема Лагранжа утверждает, что любое натуральное число можно представить в виде суммы не более, чем четырех точных квадратов. Пять, например, вы ну никак не представите в виде суммы четырех квадратов, поэтому не стоит зацикливаться на четырех итерациях.

py.user.next
Надо взять корень числа. Потом от этого корня взять целую часть, возвести её в квадрат и вычесть из числа. Для остатка проделать всё то же самое. Так максимум за четыре шага ты найдёшь все числа.
При всей привлекательности такого метода ,как ни странно но нет, хотя очень много чисел удасться разложить подобным методом но, например, 23 по такой методе раскладывается на 5 чисел : 4, 2, 1, 1, 1, а 167 на шесть: 12, 4, 2, 1, 1, 1.
Его нужно доработать
py.user.next
PEHDOM
23 по такой методе раскладывается на 5 чисел
Там нужно тогда (если не уложился в четыре шага) из первого корня вычесть единицу и получившееся значение использовать как будто это и был корень. И это происходит тоже на каждом шаге, то есть не только для первого корня. Тут нужна рекурсивная функция, которая принимает число и максимальное количество шагов для его разложения. И так на каждом шаге при взятии корня эта функция вызывается с уменьшенным максимальным количеством шагов на единицу. Ну числа могут быть большими, поэтому надо на всех уровнях раскладывать оптимально.
Slow
PEHDOM
Comandante4ну начнем с того что вы неправильно интерпретируете теорему.Теорема Лагранжа утверждает, что любое натуральное число можно представить в виде суммы не более, чем четырех точных квадратов. Пять, например, вы ну никак не представите в виде суммы четырех квадратов, поэтому не стоит зацикливаться на четырех итерациях.

Нули вообще то тоже можно.
5 = 2**2 + 1**2 + 0**2 + 0**2
PEHDOM
Comandante4 Ну вобщем py.user.next все верно написал, наиболее оптимально будет рекурсивная функция, которая принимает число и максимальное количество шагов для его разложения.
Если вам интерсно самому сделать, пробуйте. Сразу скажу готовое решение есть(и не одно), но пока не буду его приводить, вдруг вы хотите сами разобраться.

Теперь замечания по поводу именно вашего алгоритма.
1. нет смысла делать четыре цикла по n, максимально возможный корень будет int(n**0.5), следовательно перебирать варианты более этого значения бессмыслено. Вы получите существенный прирост в скорости даже не в разы, а на порядки.
2. вы делаете a ** 2 + b ** 2 + c ** 2 + d ** 2 каждый раз в самом вложеном цикле, хотя достаточно делать вычислять квадрат a,b,c и d соотвевенно только при их изменении, что еще добавит скорости
3. поскольку мы возводим только в квадрат, то заменить a ** 2 на а*а, это еще чутка добавит производительности, (это уже особенности алгоритма возведения в степень пайтоном).
vanyamoscow
PEHDOM
PEHDOM
Сразу скажу готовое решение есть(и не одно), но пока не буду его приводить, вдруг вы хотите сами разобраться.

Добрый вечер! А не могли бы вы мне решение в виде рекурсивной функции в личку скинуть. Спасибо!
al_orange
PEHDOM, пожалуйста, проверцте личку

vanyamoscow, пожалуйста, поделитесь решением, если раздобыли, а пока не справилась с этой задачкой
py.user.next
Оптимизировал без рекурсии. Сделал юнит-тесты.

Идея с последовательным вычислением корней не сработала.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB