Nombre Password [ Regístrate ]

El tamaño no es lo importante (OIE 4 - 2000) - Solución

 

Supongamos que se quieren multiplicar dos enteros de n cifras, con n lo suficientemente grande como para no caber en una variable entera (n>10). El algoritmo que todo el mundo usaría primero sería el mismo que se utiliza para resolver el problema "a mano", esto es, multiplicar cada cifra del segundo número por todas las del primero, y sumar los resultados:

  1111
*  123
------
  3333
 2222
1111
------
136653

El tiempo de ejecución de este algoritmo es de O(n2), pero se puede intentar mejorar. Ahora dividimos los números en dos partes iguales; el 1111 se dividiría en 11·102 + 11 y el 123 se dividiría en 1·102 + 23. Ahora la multiplicación se puede hacer:

XiXd·YiYd = Xi·Yi·10n + (Xi·Yd+Xd·Yi)·10n/2 + Xd·Yd
1111·123 = 11·102·1·102 + 11·102·23 + 1·102·11 + 11*23 = 136653

Teniendo en cuenta que la multiplicación por una potencia de 10 consiste en añadir ceros, y que la suma es una operación lineal, ahora el problema queda subdividido en cuatro subproblemas de tamaño n/2, con un tiempo de combinación de soluciones lineal, con lo que T(n) = 4·T(n/2) + O(n), y como se vio arriba esto equivale a T(n) = O(n2), lo que no mejora el algoritmo inicial. Para mejorarlo habría que dividir el problema en menos de 4 subproblemas. Esto se puede hacer teniendo en cuenta que Xi·Yd+Xd·Yi = (Xi-Xd)·(Yd-Yi) + Xi·Yi + Xd·Yd , con lo que sólo se necesitan tres multiplicaciones diferentes, siendo ahora el tiempo de ejecución T(n) = 3·T(n/2) + O(n), o lo que es lo mismo, T(n) = O(nlog23) = O(n1.59), que mejora considerablemente el tiempo cuadrático del método inicial. Para acabar el algoritmo bastaría con añadir una recursión que vaya solucionando los subproblemas, y poner el umbral en, por ejemplo, 4 cifras, con lo que se podría realizar la multiplicación normal.

 

Código

Código fuente en C



© (2001-2008) ALGORITMIA.NET - Política de privacidad