Большинство пропускают важную часть вашего вопроса:
Я должен хранить 0 с самого правого ди git
10 имеет факторы 2 и 5 Таким образом, вам нужно только сохранить, как часто каждое число от 1 до 23 можно разделить на 2 и 5.
Например, с 10:
i 1 2 3 4 5 6 7 8 9 10 SUM
div2 0 1 0 2 0 1 0 3 0 1 8
div5 0 0 0 0 1 0 0 0 0 1 2
Как мы видим, минимум обеих сумм равен 2
, поэтому 10!
должно заканчиваться на 00
.
Действительно, 10!
равно 3628800
.
Математика за этим стоит 10! = x * 2^8 * 5^2
, для некоторых х, которые могут не делится на 2 или 5.
Другое наблюдение состоит в том, что число 5 увеличивается намного медленнее, поэтому мы можем пропустить подсчет 2 с.
С этим знанием мы можем вычислить число конечных 0, проверяя, как часто каждое число делится на 5:
private static int numZerosInFactorial(int n) {
int divBy5 = 0;
for (int i = 1; i <= n; i++) {
for (int j = i; (j % 5) == 0; j /= 5) {
divBy5++;
}
}
return divBy5;
}
(Есть несколько небольших улучшений, которые вы можете сделать с помощью вышеуказанного метода)
Другой вопрос теперь: Вам действительно нужно значение n!
?
И если да, то с какой точностью? Можно ли рассчитывать n!
с double
сейчас?
Благодаря комментарию от Майкл , я заметил, что мы на самом деле можем рассчитать факториал без нулей, а затем использовать конкатенацию строк для отображения результата.
При вычислении факториала без нулей мы должны в основном делать то, что мы делали в numZerosInFactorial
, поэтому вместо умножения на кратное 5, мы делим на 2:
private static long factorialWithoutZeroes(int n) {
long result = 1;
for (int i = 1; i <= n; i++) {
long div = 1;
int j;
for (j = i; (j % 5) == 0; j /= 5) {
div *= 2;
}
result = result / div * j;
}
return result;
}
Окончательный результат будет:
// We have already read n from stdin
long fac = factorialWithoutZeroes(n);
int num10 = numZerosInFactorial(n);
System.out.println(n + "! = " + (fac + "0".repeat(num10)) + " (fac = " + fac + " , num10 = " + num10 + ")");
Действительно, этот подход работает до n == 23
. И выходной формат - хороший намек на то, что это ожидаемый подход.