Teorema Chino del Resto
El Teorema Chino del Resto (al que nos referiremos como CRT en el resto de este artículo) fue descubierto por el matemático chino Sun Zi.
Formulación
Sea , donde los son coprimos dos a dos. Además de los , se nos da un sistema de congruencias
\right.
donde los son constantes dadas. La forma original del CRT afirma entonces que el sistema de congruencias dado siempre tiene una y exactamente una solución módulo .
P. ej. el sistema de congruencias
\right.
tiene la solución módulo , porque , y . Podemos escribir todas las soluciones como para .
Corolario
Una consecuencia del CRT es que la ecuación
es equivalente al sistema de ecuaciones
\right.
(Como arriba, suponemos que y que los son coprimos dos a dos).
Solución para dos módulos
Consideremos un sistema de dos ecuaciones para coprimos:
\right.
Queremos hallar una solución para . Usando el Algoritmo de Euclides extendido podemos hallar coeficientes de Bézout tales que
De hecho y son simplemente los inversos modulares de y módulo y . Tenemos así que , y viceversa .
Con esos dos coeficientes podemos definir una solución:
Es fácil verificar que esto es efectivamente una solución calculando y .
Nótese que el Teorema Chino del Resto también garantiza que existe solo 1 solución módulo . Esto también es fácil de demostrar.
Supongamos que hay dos soluciones distintas e . Como e , se sigue que y por lo tanto o, de forma equivalente, . Así que e son en realidad la misma solución.
Solución para el caso general
Solución inductiva
Como es coprimo con , podemos aplicar de forma inductiva y repetida la solución para dos módulos para cualquier cantidad de módulos. Primero se calcula usando las dos primeras congruencias, luego se puede calcular usando las congruencias y , etc.
Construcción directa
Es posible una construcción directa similar a la interpolación de Lagrange.
Sea , el producto de todos los módulos excepto , y los inversos modulares . Entonces una solución del sistema de congruencias es:
Podemos comprobar que esto es efectivamente una solución calculando para todo . Como es un múltiplo de para , tenemos
Implementación
struct Congruence {
long long a, m;
};
long long chinese_remainder_theorem(vector<Congruence> const& congruences) {
long long M = 1;
for (auto const& congruence : congruences) {
M *= congruence.m;
}
long long solution = 0;
for (auto const& congruence : congruences) {
long long a_i = congruence.a;
long long M_i = M / congruence.m;
long long N_i = mod_inv(M_i, congruence.m);
solution = (solution + a_i * M_i % M * N_i) % M;
}
return solution;
}Solución para módulos no coprimos
Como se mencionó, el algoritmo anterior solo funciona para módulos coprimos .
En el caso no coprimo, un sistema de congruencias tiene exactamente una solución módulo , o no tiene solución en absoluto.
P. ej. en el siguiente sistema, la primera congruencia implica que la solución es impar, y la segunda implica que la solución es par. No es posible que un número sea a la vez impar y par, por lo tanto claramente no hay solución.
\right.
Es bastante sencillo determinar si un sistema tiene solución. Y si la tiene, podemos usar el algoritmo original para resolver un sistema de congruencias ligeramente modificado.
Una sola congruencia es equivalente al sistema de congruencias donde es la factorización prima de .
Con este hecho, podemos modificar el sistema de congruencias en un sistema que solo tiene potencias de primos como módulos. P. ej. el sistema de congruencias anterior es equivalente a:
\right.
Como originalmente algunos módulos tenían factores comunes, obtendremos algunas congruencias con módulos basados en el mismo primo, aunque posiblemente con distintas potencias de primo.
Se puede observar que la congruencia con el módulo de mayor potencia de primo será la congruencia más fuerte de todas las basadas en el mismo número primo. O bien dará una contradicción con alguna otra congruencia, o ya implicará todas las demás.
En nuestro caso, la primera congruencia implica , y por lo tanto contradice la segunda congruencia . Por lo tanto este sistema de congruencias no tiene solución.
Si no hay contradicciones, entonces el sistema de ecuaciones tiene una solución. Podemos ignorar todas las congruencias excepto las que tienen los módulos de mayor potencia de primo. Estos módulos ahora son coprimos, y por lo tanto podemos resolver este sistema con el algoritmo discutido en las secciones anteriores.
P. ej. el siguiente sistema tiene una solución módulo .
\right.
El sistema de congruencias es equivalente al sistema:
\right.
Las únicas congruencias con el mismo módulo primo son y . La primera ya implica la segunda, así que podemos ignorar la segunda y resolver en su lugar el siguiente sistema con módulos coprimos:
\right.
Tiene la solución , y en efecto y .
Algoritmo de Garner
Otra consecuencia del CRT es que podemos representar números grandes usando un arreglo de enteros pequeños.
En lugar de hacer muchos cálculos con números muy grandes, lo cual puede ser costoso (pensemos en hacer divisiones con números de 1000 dígitos), se pueden elegir unos cuantos módulos coprimos y representar el número grande como un sistema de congruencias, y realizar todas las operaciones sobre el sistema de ecuaciones. Cualquier número menor que se puede representar como un arreglo , donde .
Usando el algoritmo anterior, se puede reconstruir de nuevo el número grande cuando se necesite.
Como alternativa, se puede representar el número en la representación de base mixta (mixed radix):
El algoritmo de Garner, que se discute en el artículo dedicado algoritmo de Garner, calcula los coeficientes . Y con esos coeficientes se puede restaurar el número completo.