Hmm… Já que estamos falando em fatorial, deixa eu postar um problema aqui que envolve fatorial (e que até poderíamos colocar na MathUtils, apesar de eu não conhecer nenhuma utilidade para a função que irei apresentar).
A função Z(n) é uma função que recebe um número natural como parâmetro e retorna o número de zeros presentes no final do fatorial desse número. Por exemplo:
Z(5): 5 * 4 * 3 * 2 * 1 = 120. O número de zeros no final de 120 é 1, então Z(5) é igual a 1.
Z(10): 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 3628800. O número de zeros no final é 2, então Z(10) é igual a 2.
Outros exemplos: Z(60) = 14, Z(100) = 24, etc. O n pode ser um número muito grande. Posso querer saber Z(1000), por exemplo.
Como resolver esse problema? Obviamente, calcular o fatorial e contar o número de zeros não é viável. A minha solução foi a seguinte: o número de zeros no final vai depender do número de 10 presentes na multiplicação, por exemplo:
Z(5): 5 * 4 * 3 * 2 * 1 => 10 * 4 * 3 * 1 => Um 10, então possui um zero no final.
Z(10): 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 => 10 * 9 * 8 * 7 * 6 * 10 * 4 * 3 * 1 => Dois 10, então possui dois zeros no final.
Mas é possível simplificar isso dizendo que o número de zeros no final é igual ao número de 5s na multiplicação, tendo em vista que o número de 2s que existem na multiplicação é bem maior que o de 5s e esses 2s que sobram não influenciam no número de 10s, pois o 2 precisa estar com o 5 pra produzir um 10.
Exemplo:
10! = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1
Z(10!) = (2*5 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1) = Dois cincos, dois zeros no fim.
30! = 30 * 29 * 28 * 27 * … * 6 * 5 * 4 * 3 * 2 * 1
Z(30!) = 30 * 25 * 20 * 15 * 10 * 5 (descartamos o restante pois precisamos apenas dos múltiplos de 5)
Z(30!) = 65 * 55 * 45 * 35 * 2*5 * 5 = Sete cincos, implica em 7 zeros no final.
Pra contar o número de 5s, eu fiz essa função:
public static int z(int n) {
int cincos = 0; // o número de cincos
int aux;
while (n > 0) {
aux = n;
while (aux > 0) {
if (aux%5 == 0)
cincos++;
else
break;
aux /= 5;
}
n--;
}
return cincos;
}
Esse código está retornando o resultado certo, mas ele tem complexidade O(n log n) e o local onde eu vi o problema dizia que dava pra fazer com O(log n). Alguém tem alguma idéia de como fazer isso?