2010-01-20 122 views
12

Entiendo que este es un problema clásico de programación y, por lo tanto, quiero dejar claro que no estoy buscando el código como solución, pero agradecería un empujón en la dirección correcta. Estoy aprendiendo C++ y como parte del proceso de aprendizaje estoy intentando algunos problemas de programación. Estoy intentando escribir un programa que trata con números hasta factorial de 1 billón. Obviamente, estos serán números enormes y demasiado grandes para tratar con el uso de operaciones aritméticas normales. Cualquier indicación en cuanto a qué dirección debería tomar para tratar de resolver este tipo de problema sería apreciada.Cálculo de factoriales grandes en C++

prefiero tratar de resolver esto sin usar las bibliotecas adicionales, si es posible

Gracias

PS - el problema es que aquí http://www.codechef.com/problems/FCTRL


Aquí está el método que utiliza para resolver el problema Esto se logró leyendo los comentarios a continuación:

Solución: el número 5 es un factor primo de cualquier número que termine en cero. Por lo tanto, dividiendo el número factorial por 5, recursivamente, y agregando los cocientes, obtienes el número de ceros finales en el resultado factorial

E.G. - ¡Número de ceros finales en 126! = 31

126/5 = 25 resto 1

25/5 = 5 resto 0

5/5 = 1 resto 0

25 + 5 + 1 = 31

Esto funciona para cualquier valor, solo siga dividiendo hasta que el cociente sea menor que 5

+1

Dupe: http://stackoverflow.com/questions/1966077/calculate-the-factorial-of-an-arbitrarily-large-number-showing-all-the-digits –

+2

No es realmente un dup. El problema de OP se puede resolver sin conocer ninguno de los dígitos del factorial :-) – ephemient

+3

No es un dup en absoluto, porque resolver este problema calculando todos los dígitos del factorial no tiene ninguna posibilidad de entrar en el límite de 8s en este problema. Factorial mil millones empuja 9 mil millones de dígitos decimales de largo, por lo que estaría manipulando alrededor de 3-4 GB de datos. –

Respuesta

6

desnatada esta pregunta, no está seguro de si realmente lo hizo bien, pero aquí es una conjetura deductiva:

Primera pregunta - ¿cómo se obtiene un cero en el final del número? Al multiplicar por 10.

¿Cómo se multiplica por 10? ya sea multiplicando por un 10 o por 2 x 5 ...

Entonces, ¡para X! ¿Cuántos 10s y 2x5s tienes ...?

(por suerte 2 & 5 son números primos)

editar: Aquí hay otra sugerencia - No creo que lo que necesita hacer ningún multiplicación. Avísame si necesitas otra pista.

+2

No lo creo (b/c no sé qué teoría de números es). Aquí hay otra pista ... X! = 1 x2..x5..10..12..15..20..22..25..30 ..... X Esos números le darán 6 ceros. ¿Cuántos ceros te dará X? – james

+0

Gracias James, con tu gran impulso (lol) lo resolví en 1,42 segundos. Bueno, tres días, pero el programa lo resuelve en 1,42 segundos. ¡Gracias a todos los que contribuyeron! – conorgriffin

+0

@Griffo Veo que el más rápido lo hace en menos de 0.05 segundos, ¿cómo es esto posible? – TiansHUo

0

Para comenzar, debe almacenar el número en un tipo de matriz como un st d :: vector (un dígito para cada posición en la matriz) y necesita encontrar un determinado algoritmo que calculará un factorial (tal vez en algún tipo de clase especializada). ;)

+0

repitiendo otro comentario, el crecimiento factorial es más rápido que el crecimiento exponencial. Si está calculando mil millones de factoriales, la respuesta será aproximadamente la mitad de un billón de billones (aproximadamente 15 gigabits, 1920 MB). Multiplique por dos o tres si mantiene dígitos decimales en bytes. – Potatoswatter

3

Sugerencia: es posible que no necesite calcular N! para encontrar la cantidad de ceros al final de N!

+0

Gracias, eso es una ayuda entonces.Me hace pensar de una manera diferente; o) – conorgriffin

1

Esta no es una buena respuesta a su pregunta ya que la ha modificado un poco de lo que leí originalmente. Pero lo dejaré aquí de todos modos para demostrar la impracticabilidad de tratar de hacer los cálculos por la fuerza bruta principal.

Un mil millones de factoriales estará fuera del alcance de cualquier biblioteca bignum. Tales números requerirán más espacio para representar que casi cualquier persona tiene en RAM. Tendrás que comenzar a buscar los números desde el almacenamiento mientras trabajas en ellos. Hay formas de hacer esto.El guy who recently calculated π out to 2700 billion places usó dicha biblioteca

+0

Sí, olvidé decir originalmente que no quería usar una biblioteca bignum. Gracias por la respuesta de todos modos, sin duda es útil comprender la impracticabilidad de un método de fuerza bruta. – conorgriffin

2

Para resolver esta pregunta, como dijo Chris Johnson, debe mirar el número de 0.

Los factores de 10 serán 1,2,5,10 en sí. Entonces, ¡puedes revisar cada uno de los números de N! y escríbalos en términos de 2^x * 5^y * 10^z. Descarta otros factores de los números.

Ahora la respuesta será mayor de (x, y) + z.

Una cosa interesante que aprendo de esta pregunta es que siempre es mejor almacenar factoriales de un número en términos de factores primos para facilitar las comparaciones.

De hecho, x^y, hay un método fácil de usar en el algoritmo RSA, que no recuerdo. Intentaré actualizar la publicación si encuentro una.

+0

¡Ah, gran idea! Gracias, lo pensaré un poco. – conorgriffin

+1

Solo necesita lidiar con los factores primos (2 y 5). La manera más fácil que conozco de encontrar los exponentes es dividiéndolos, p. 'while (! (N% 5)) {n/= 5; y ++;} ' –

+0

Siento que 10 también debería incluirse porque, ahorra un cheque adicional :-). – Boolean

1

Creo que debe encontrar una manera de resolver el problema en un pseudo código antes de empezar a pensar en C++ o en cualquier otro idioma. La naturaleza de la pregunta, como algunos han señalado, es más un problema de algoritmo que un problema de C++. Aquellos que sugieren buscar alguna biblioteca oscura te están apuntando en una pendiente resbaladiza, porque aprender a programar es aprender a pensar, ¿no? Encuentre un buen texto de análisis de algoritmo y le servirá bien. En nuestro departamento enseñamos a partir del texto CLRS.

0

Para calcular grande factorial, puede utilizar este código en C++:

#include<iostream> 
using namespace std; 

long double factorial(int n); 

int main() 
{ 
    int n; 

    cout << "Enter a positive integer: "; 
    cin >> n; 

    cout << "Factorial of " << n << " = " << factorial(n); 

    return 0; 
} 

long double factorial(int n) 
{ 
    if(n > 1) 
     return n * factorial(n - 1); 
    else 
     return 1; 
} 

A medida que el tiempo doble tiene grandes datos 1.7E +/- 308, este código puede realmente funcionar bien !!

Cuestiones relacionadas