100! большое число:
100! = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
Чтобы быть более точным, требуется ~ 525 бит и не может быть вычислено без какой-либо формы bigint
математики.
Однако конечные нули могут быть вычислены на обычных целых числах:
Идея состоит в том, чтобы ограничить результат по-прежнему вписываться в ваш тип данных. Поэтому после каждого итерационного теста результат делится на 10. Если он увеличивается, то счетчик нулей увеличивается и делится на 10, пока вы можете. То же самое относится и к любым простым числам, кроме тех, которые делят 10, поэтому нет: 2,5
(но без увеличения счетчика нулей). Таким образом, у вас будет небольшой промежуточный результат и количество конечных нулей.
Таким образом, если вы выполните 2,5
факторизацию всех мультипликаторов в n!
, то минимальное значение обоих показателей в 2,5 будет равно числу конечных нулей, поскольку каждая пара выдает одну нулевую цифру (2*5 = 10
). Если вы понимаете, что показатель 5
всегда меньше или равен показателю 2
, этого достаточно для факторизации 5
(так же, как вы делаете это в своем обновленном коде).
int fact_trailing_zeros(int n)
{
int i,n5;
for (n5=0,i=5;n>=i;i*=5) n5+=n/i;
return n5;
}
С результатами:
Trailing zeors of n!
10! : 2
100! : 24
1000! : 249
10000! : 2499
100000! : 24999
1000000! : 249998
10000000! : 2499999
100000000! : 24999999
[ 0.937 ms]
Однако 100!
содержит также непоследних нулей и для вычисления тех, которые я не вижу другого способа, кроме вычисления реальной вещи по bigint
математике ... но это не означает, что нет обходного пути как для конечных нулей ...
Если это поможет, здесь вычисляются факториалы вплоть до 128!
, поэтому вы можете проверить свои результаты:
Если n
ограничено достаточно малым значением, вы можете использовать LUT , сохраняя все факториалы до предела в виде строк, или BCD и просто отсчитывать нули оттуда. .. или даже иметь только окончательные результаты в виде LUT ...