Estaba buscando aquí y noté que el mejor tiempo de ejecución para la multiplicación de dos números de bits es O ( n ⋅ log n ⋅ 2 O ( log ∗ n ) , pero puedo notar fácilmente un algoritmo que se ejecuta en O ( n ⋅ log n ) .
Después de todo, sabemos cómo multiplicar dos polinomios de grado en tiempo de ejecución O ( n log n ) . Pero multiplicar polinomios es lo mismo que multiplicar dos números de n bits. Entonces tenemos un algoritmo para multiplicar dos números de n bits en O ( n log n ) . Ahora, el único problema que puede ocurrir es el carry, pero en cada fase podemos solucionarlo en el tiempo O ( n ) , simplemente moviéndonos en el bit más correcto y su vecino izquierdo, hasta el final. Es decir, nuestro tiempo de ejecución seguirá siendo O ( n ⋅ log n .
Entonces, ¿hice un descubrimiento nuevo (y bastante obvio)? ¿O la página de Wikipedia está desactualizada? ¿O tal vez tengo algún error?
fuente
Respuestas:
Como @DavidRicherby ya señala, la confusión surge porque se mezclan diferentes medidas de complejidad. Pero déjame explicar un poco.
Por lo general, cuando se estudian algoritmos para la multiplicación polinómica sobre anillos arbitrarios, uno está interesado en la cantidad de operaciones aritméticas en el anillo que usa un algoritmo. En particular, dado un anillo (conmutativo, unitario) y dos polinomios f , g ∈ R [ X ] de grado menor que n , el algoritmo de Schönhage-Strassen necesita multiplicaciones y adiciones O ( n log n log log n ) en R para calcular f g ∈ R [ X ]R f,g∈R[X] n O(nlognloglogn) R fg∈R[X] por, más o menos, contiguo raíces primitivas -ésimos de unidad a R para conseguir algo de anillo más grande D ⊃ R y luego, utilizando la transformada rápida de Fourier sobre D , calculando el producto en D .n R D⊃R D D
Si su anillo contiene un raíz-ésima de la unidad, entonces esto puede ser acelerado a O ( n log n ) las operaciones en R mediante el uso de la transformada rápida de Fourier directamente sobre R . Más específicamente, sobre Z ⊂ C , puede hacer esto usando operaciones de anillo O ( n log n ) (ignorando el hecho de que esto requeriría una aritmética exacta sobre los números complejos).n O(nlogn) R R Z⊂C O(nlogn)
La otra medida que se puede tener en cuenta es la complejidad de bits de una operación. Y esto es lo que nos interesa al multiplicar dos enteros de longitud de bits . Aquí, las operaciones primitivas se multiplican y agregan dos dígitos (con carry). Entonces, al multiplicar dos polinomios sobre Z , en realidad debe tener en cuenta el hecho de que los números que surgen durante el cálculo no se pueden multiplicar utilizando un número constante de operaciones primitivas. Esto y el hecho de que Z no tiene un n -ésima raíz primitiva de la unidad para n > 2 le impide appling la O ( n log n )n Z Z n n>2 O(nlogn) algoritmo. A superar este considerando con coeficientes del anillo Z / ⟨ 2 n + 1 ⟩ , ya que los coeficientes del polinomio producto no superará este unido. Hay (cuando n es una potencia de dos), que tiene (la clase de congruencia) 2 como n raíz ésima de la unidad, y mediante la llamada recursiva del algoritmo para la multiplicación de los coeficientes, se puede lograr un total de O ( n log n log log n ) (es decir, bit) operaciones primitivas. Esto luego se traslada a la multiplicación entera.f,g Z/⟨2n+1⟩ n 2 n O(nlognloglogn)
fuente
fuente