Flat Preloader Icon

Project Euler (answers)

Проект Эйлера: Ответ и решение 38 задачи (Пан-цифровые кратные числа)

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

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

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

Возьмем число 192 и умножим его по очереди на 1, 2 и 3:

192 × 1 = 192
192 × 2 = 384
192 × 3 = 576

Объединяя все три произведения, получим девятизначное число 192384576 из цифр от 1 до 9 (пан-цифровое число). Будем называть число 192384576 объединенным произведением 192 и (1,2,3)

Таким же образом можно начать с числа 9 и по очереди умножать его на 1, 2, 3, 4 и 5, что в итоге дает пан-цифровое число 918273645, являющееся объединенным произведением 9 и (1,2,3,4,5).

Какое самое большое девятизначное пан-цифровое число можно образовать как объединенное произведение целого числа и (1,2, … , n), где n > 1?

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

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

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

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

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

Небольшое упрощение задачи

Выше было указано, что если начать с числа 9 и перемножать его на множители (1, 2, 3, 4 и 5), то в итоге получим пан-цифровое число 918273645, вполне удовлетворяющее условиям задания. Однако, оно уже описано в условиях задачи, потому заведомо не может быть ответом.

При этом все же можно сделать вывод, что проверять необходимо только числа начинающиеся с 9 (90 – 99, 900 – 999 и т.п.), потому что иные дадут заведомо меньшее итоговое число.

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

В программе в итоге будем перебирать ряд чисел от 90 до 9999 и при этом пропускать промежутки, где заведомо нет ответа (100900, 10009000).

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

При переборе чисел, каждое из них проверяется на возможность быть ответом. Т.е. при перемножении числа на ряд множителей (1,2,3…) получится ли пан-цифровое число с помощью функции is_pandigital(), описанной ниже.

Если пан-цифровое число формируется, то с помощью функции get_concat_prod() формируется данное объединенное произведение.

Максимальное из них сохраняется как ответ.

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

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

  • #include <time.h> 

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

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

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

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

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

Функции, использующиеся в программе (проект Эйлера - 38 задача)

Функция для определения возможности получить из данного числа пан-цифровое
Функция для определения возможности получить из данного числа пан-цифровое

Функция для определения возможности получить из данного числа пан-цифровое

Чтобы определить, является ли число пан-цифровым, создадим массив для хранения цифр числа.

При этом цифры будут храниться по индексу:

  • arr[число] = 0; //нет такого числа
  • arr[число] = 1; //есть такое число

Тогда по мере внесения цифр в массив, он будет заполняться единицами:

  • 9 -> [0,0,0,0,0,0,0,0,0,1]
  • 9 * 2 = 18 -> [0,1,0,0,0,0,0,0,1,1]
  • 9 * 3 = 27 -> [0,1,2,0,0,0,0,1,1,1]
  • [0,1,1,1,1,1,1,1,1,1]

… пока в итоге не заполнится полностью (кроме нуля).

При том функция put_digits(), возвращает количество цифр занесенных в массив.

Если среди цифр не встретился ноль или цифра ранее занесенная в массив, то данное объединенное произведение является пан-цифровым и функция вернет true.

Иначе – false.

Функция, которая раскладывает число на цифры, сохраняет их в массив по индексу

Проект Эйлера (38 задача) - Функция, которая раскладывает число на цифры, сохраняет их в массив по индексу
Функция, которая раскладывает число на цифры, сохраняет их в массив по индексу

Данная функция берет младшую цифру числа:

  • num % 10

Проверяет ее отсутствие в массиве (т.е. ячейка с таким индексом равна нулю):

  • arr[num%10] == 0

И проверяет, что эта младшая цифра не является нулем:

  • Внутри условия if() num % 10 то же самое, что num % 10 != 0

Если условия соблюдены, то в массив записывается 1 по соответствующему индексу и цифра отрезается.

Иначе, возвращается цифра 10, заведомо превышающая допустимых 9 цифр в числе.

Количество цифр, заносимых в массив, при занесении в массив подсчитывается и (при корректной работе)  возвращается в итоге функцией. 

Функция для получения девятизначного объединенного произведения цифр

Проект Эйлера (38 задача) - Функция для получения девятизначного объединенного произведения цифр
Функция для получения девятизначного объединенного произведения цифр

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

Возьмем для примера число, начинающееся с 9:

  • Записываем 9 и учитываем его как одно занесенное число (len).
  • 2 *9 =18, число двузначное, потому смещение (shift) будет равно 100 и длина числа (len) увеличивается сразу на 2.
  • Девятка смещается (9 -> 900
  • Числа объединяются 900 + 18 = 918
  • 3 * 9 = 27, его смещение 100, длина – 2.
  • Смещаем число 918 -> 91800
  • …и прибавляем 27 91800 + 27 = 91827
  • и так далее.

Как только длина числа достигла девяти (согласно условиям задания), оно возвращается как результат.

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

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

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

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

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

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

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

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

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

© 2023-2024 | eulerproject.ru