Проект Эйлера (24 задача) трудна пониманием самого порядка перестановки цифр. Для решения потребовалось вводить другую систему исчисления
Узнать больше в телеграм-канале: ProjectEuler++
Перестановка – это упорядоченная выборка объектов. К примеру, 3124 является одной из возможных перестановок из цифр 1, 2, 3 и 4. Если все перестановки приведены в порядке возрастания или алфавитном порядке, то такой порядок будем называть словарным. Словарные перестановки из цифр 0, 1 и 2 представлены ниже:
012 021 102 120 201 210
Какова миллионная словарная перестановка из цифр 0, 1, 2, 3, 4, 5, 6, 7, 8 и 9?
123 -> 132 -> 213 ->231 -> 312 ->321
Однако как понять, почему цифры переставляются именно таком порядке?
Рассмотрим, как формируется первая (нулевая) выборка цифр – 123 (Рисунок 1):
- [1,2,3] забираем 1 arr[0]
- [2,3] забираем 2 arr[0] – не arr[1]!!!
- [3] забираем 3 arr[0] – не arr[2]!!!
Если остальные числа перестановки чисел 1 2 3 преобразовать подобным образом, вся перестановка обретает смысл и становится видна логика перестановки:
В итоге мы получаем шесть искомых перестановок в виде чисел-из-индексов. При этом нулевая перестановка будет 000, а последняя, пятая – 210 (Рисунок 2). Однако нужно понимать ряд особенностей такой системы:
Например, для 4-й перестановки цифр 123, мы получаем число-из-индексов 200 (смотрите рисунок 2). Далее чтобы получить искомое значение перестановки промежуточное число 200 трансформируется следующим образом:
В итоге мы имеем следующую цепочку:
Переставляемые цифры 0, 1, 2, 3, 4, 5, 6, 7, 8 и 9 сохраним в массив.
Данная перестановка будет иметь номер-из-индексов 0000000000 и, по сути, будет не первой, а нулевой. Потому будем искать не миллионную перестановку, а 999999-ю.
Промежуточный ответ, в виде числа-из-индексов будем сохранять в отдельном массиве:
Далее задача будет решаться буквально в два действия:
Для измерения времени работы программы подключаем библиотеку time.h:
С помощью функции clock() измеряем время начала (begin) и окончания (end) работы программы. В итоге время работы будем находить как разность между ними.
(double) приводит число (в данном случае – результат вычислений end – begin) к вещественному типу данных double (числа с точкой)
CLOCKS_PER_SEC – это константа, сохраненная в библиотеке и зависящая от типа устройства, на котором запускается программа. В данном случае – это просто 1000
Поскольку нам многократно понадобятся значения факториалов чисел, потому вычислим их заранее. Сохранив их в массив по индексу, мы в итоге, сможем получать значение факториала просто обращаясь к нему:
Далее функция делит число (номер перестановки) на факториал 9! (для старшего разряда) заносит в первую ячейку массива indx_arr[]. Остаток от деления делится на 8! и результат заносится в следующую. И так до конца массива.
Однако, возможно после прохождения и заполнения всего массива, останется остаток. Это значит номер перестановки больше возможного и для данной комбинации цифр, такой перестановки не существует. В таком случае будет выведено предупреждение.
Данная функция вычисляет факториалы чисел от нуля, до заданного числа и сохраняет их в массив. В итоге это позволяет не вычислять их многократно и обращаться к ним по индексу в массиве.
Также, функция возвращает значение последнего вычисленного факториала.
Как ясно из названия, функция сравнивает два значения.
Если контролируемое значение превысит свой предел, то функция вернет true и выведет предупреждение.
Иначе вернет false.
Очень простая, однако, очень важная и полезная функция. Помогает как при отладке, так и при повторном использовании функций в других программах. Поскольку в других задачах другие условия, потому контекст применения функций может поменяться. Потому важно ограничивать параметры принимаемых функцией значений и выводить соответствующие предупреждения.
Решил не усложнять функцию и не сохранять искомую перестановку в виде числа или массива, а сразу выводить на экран.
Функция работает следующим образом:
В итоге ответ на 24 задачу проекта Эйлера составил 2783915460, программа считает ответ мгновенно – за 0.0000000 секунды.
По традиции хотелось бы выразить глубочайшую признательность Сергею Балакиреву за его титанический труд по созданию бесплатных курсов и в частности, за “Язык программирования C/C++ для начинающих“.
© 2023-2024 | eulerproject.ru