Найти тему

Задача 18. Факториал

Решим сложную задачу на двух языках. Читаем условие:

Условие задачи с сайта acmp.ru
Условие задачи с сайта acmp.ru

Алгоритмически решается задача очень просто: надо перебрать все числа от 1 до n и перемножить их. И именно так и надо делать. Например на Python.

Считаем входное число и приведём его к числовому типу:

Считываем входные данные
Считываем входные данные

Затем заведём переменную, в которой будем накапливать ответ. И инициализируем её единицей. Обращу внимание, что не нулём, потому что будем домножать её, а не прибавлять к ней. И запустим цикл, в котором выполним умножения:

Вычисление факториала
Вычисление факториала

Осталось вывести ответ:

Вывод ответа
Вывод ответа

И этим решением легко сдать задачу. Также, несложно сдать эту задачу на Pascal ABC или Java. Это всё из-за того, что в этих языках программирования в базовой комплектации есть числовые типы, которые поддерживают числа неограниченной длины. Так называемая длинная арифметика.

С С++ всё намного интереснее. Основные этапы решения остаются такими же, но необходимо самостоятельно реализовать работу с большими числами.

В этой задаче большое число нам потребуется ровно одно. Будем его хранить в массиве по три цифры числа в каждом элементе. Тогда нам хватит массива длины 999. Подключим библиотеку ввода и определим массив для большого числа:

Определение массива для хранения ответа
Определение массива для хранения ответа

Первым делом заведём переменную n и считаем её:

Ввод входных данных
Ввод входных данных

Ещё мы завели переменную p, которую будем использовать для разных вспомогательных действий.

Как и в решении на Python инициализируем ответ и запустим цикл до n:

Цикл для вычисления факториала
Цикл для вычисления факториала

Так как длина большого числа может меняться, а длина массива фиксирована, то большие числа принято хранить в обратном порядке. То есть в нулевом элементе будут единицы, десятки и сотки; в первом - тысячи, десятки и сотни тысяч; и так далее - чем больше индекс в массиве, тем выше разряды. Поэтому массив [1, 0, 0, 0, ...] обозначает число 1.

Внутри обозначенного цикла необходимо выполнить умножение длинного числа на i. Для того надо пройти по всему числу (в идеале не по всему, а до крайнего ненулевого элемента, но так как в нашем случае длина строго ограничена, можно идти до конца массива) и каждый его разряд умножить на i. Делаем ровно так, как это делается при умножении в столбик. Но при этом могут возникнуть переносы в следующий разряд (когда при умножении получается число больше 999), их будем запоминать в переменную p и на следующей итерации цикла прибавлять:

Уножение длинного числа на обычное
Уножение длинного числа на обычное

После этого цикла можно считать, что ответ готов. Но теперь его надо правильно вывести, так нельзя просто так взять и вывести массив. Так как мы не поддерживали длину числа, то надо будет идти с самого старшего разряда и пропустить все нули:

Вывод ответа
Вывод ответа

А второй момент возникает из-за того, что мы храним сразу по три цифры. И, например, для числа 12045 (которое в массиве будет [45, 12, 0, ...]) при простом выводе получим 1245. Для избежания такой ситуации внутри цикла есть условия на вывод ведущих нулей.

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

Предыдущий выпуск: Задача 293. Налоги

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