Flat Preloader Icon

Project Euler (answers)

Проект Эйлера: Ответ и решение 39 задачи (Целые прямоугольные треугольники)

Проект Эйлера (39 задача). Несложная задача на стишок про “Пифагоровы штаны”. По сути, легко решается перебором, однако и его можно ускорить.

Узнать больше в телеграм-канале: ProjectEuler++

Условия задачи

Если p – периметр прямоугольного треугольника с целочисленными длинами сторон {a,b,c}, то существует ровно три решения для p = 120:

{20,48,52}, {24,45,51}, {30,40,50}

Какое значение p ≤ 1000 дает максимальное число решений?

Добро пожаловать на сайт))

Решение (проект Эйлера - 39 задача)

Проект Эйлера (39 задача) - решение, часть 1
Решение, часть 1

Все решение уместилось в функции main(), потому чтобы не “мельчить”, решил разбить ее на два скриншота.

Проект Эйлера (39 задача) - решение, часть 2
Решение, часть 2

Пифагоровы штаны во все стороны равны

Данный стишок в школе помогал запомнить теорему Пифагора:

Треугольник, у которого сумма квадратов длин двух сторон равна квадрату длины третьей стороны, является прямоугольным.

Пифагоровы штаны
Пифагоровы штаны

Действительно, если нарисовать, получается очень похоже.

Данная теорема дает нам формулу для проверки удовлетворения условий задачи:

  • a^2 + b^2= c^2
Таким образом, если просто перебрать все значения сторон треугольника a, b, c и подставить в формулу, можно легко получить ответ. Однако легко посчитать, что 1000 * 1000 * 1000 даст целый миллиард возможных комбинаций.

Улучшаем алгоритм программы

Можно не перебирать все возможные треугольники и выбирать из них прямоугольные, как описано выше, а сразу получать прямоугольные треугольники. Для этого будем перебирать только катеты треугольника a и b, а гипотенузу c будем вычислять:

  • c = sqrt(a^2 + b^2)

При этом условиям задачи треугольник будет соответствовать, если гипотенуза целочисленная. 
Это сразу уменьшит объем вычислений на три порядка, однако как вычислять квадратный корень? Стандартная функция sqrt() работает с вещественными числами типа double, и потому не дает нам возможности понять, целое ли число или нет.
В программе я решил вычислить квадраты натуральных чисел и сохранить их в массив по индексу.

  • массив[квадрат числа] = число;
  • arr[4] = 2;
  • arr[9] = 3;

Поскольку остальная часть массива заполнена нулями, потому достаточно обратиться к нему, чтобы понять целочисленный ли квадратный корень из числа или нет.

  • arr[16] = 4; // корень из 16 равен 4
  • arr[17] = 0; // корень из 17 – дробное число

Алгоритм работы программы

Кроме того, нам понадобится массив для подсчета ответов. Индексом массива будет являться периметр треугольника, а значением ячейки – количество возможных решений для данного периметра (смотрите выше).

В программе перебираются два катета a и b  в двух циклах for(). При этом:

  • Один катет всегда больше другого (b > a). Делаем так, потому что иначе одни и те же ответы повторятся два раза (a = 3, b = 4 и a = 4, b = 3, например).
  • Учитываем, что сумма катетов a и b не может быть больше 1000.

После нахождения целочисленной гипотенузы (c), также учитываем только те ответы, при которых периметр треугольника (a+b+c) меньше 1000.

Каждый найденный ответ увеличивает количество решений для данного конкретного периметра – индекса в массиве ответов. 

После перебора всех катетов и подсчета всех возможных вариантов, остается в итоге только пройтись по массиву и выбрать периметр с максимальным количеством решений.

Измеряем время работы программы

Для измерения времени работы программы подключаем библиотеку time.h:

  • #include <time.h> 

С помощью функции clock() измеряем время начала (begin) и окончания (end) работы программы. В итоге время работы будем находить как разность между ними.

* Примечания:

clock_t это тип данных, определенный через typedef. По сути это обычный целочисленный long

(double) приводит число (в данном случае – результат вычислений end – begin) к вещественному типу данных double (числа с точкой)

CLOCKS_PER_SEC – это константа, сохраненная в библиотеке и зависящая от типа устройства, на котором запускается программа. В данном случае – это просто 1000

Ответ и скорость работы программы (проект Эйлера - 39 задача)

Проект Эйлера (39 задача) - ответ
39 задача ответ

В итоге ответ на 39 задачу проекта Эйлера составил 840, программа считает ответ практически мгновенно. 

По традиции хотелось бы выразить глубочайшую признательность Сергею Балакиреву за его титанический труд по созданию бесплатных курсов и в частности, за “Язык программирования C/C++ для начинающих“.

проект Эйлера
Курс "C/C++ для начинающих"

Есть вопросы, господа? Отвечаем спокойно, четко и только по делу))

Есть вопросы, господа?

Проект Эйлера (ответы) | © 2023-2024 | eulerproject.ru

Проект Эйлера (ответы) | © 2023-2024 | eulerproject.ru

© 2023-2024 | eulerproject.ru