Uso del teorema chino del resto para combinar ecuaciones modulares

Dadas N ecuaciones modulares: A ≅ x 1 mod(m 1 ) . . A ≅ x n mod(m n ) Encuentra x en la ecuación A ≅ xmod(m 1 *m 2 *m 3 ..*m n ) donde m i es primo, o potencia de un primo, e i toma valores de 1 a n. La entrada se da como dos arrays, la primera es una array que contiene valores de cada x i y la segunda array contiene el conjunto de valores de cada número primo. m i Muestra un número entero para el valor de x en la ecuación final. Ejemplos: 

Consider the two equations
A ≅ 2mod(3)
A ≅ 3mod(5)
Input : 
2 3
3 5
Output : 
8

Consider the four equations,
A ≅ 3mod(4)
A ≅ 4mod(7)
A ≅ 1mod(9) (32)
A ≅ 0mod(11)
Input :
3 4 1 0
4 7 9 11
Output :
1243

Explicación: nuestro objetivo es resolver estas ecuaciones de dos en dos. Tomamos las dos primeras ecuaciones, las combinamos y usamos ese resultado para combinarlas con la tercera ecuación, y así sucesivamente. El proceso de combinar dos ecuaciones se explica a continuación, tomando el ejemplo 2 como referencia:

  1. A ≅ 3mod(4) y A ≅ 4mod(7) son las dos ecuaciones que nos proporcionan en un principio. Sea la ecuación resultante un A 0 ≅ x 0 mod(m 1 * m 2 ).
    • Un 0 viene dado por m 1 ‘ * m 1 * x 0 + m 0 ‘ * m 0 * x 1 donde m 1 ‘ = inversa modular de m 1 módulo m 0 y m 0 ‘ = inversa modular de m 0 módulo m 1
    • Podemos calcular el inverso modular usando el algoritmo euclidiano extendido.
    • Encontramos que x 0 es A 0 mod (m 1 * m 2 )
    • Conseguimos que nuestra nueva ecuación sea A ≅ 11mod(28), donde A es 95
  2. Ahora tratamos de combinar esto con la ecuación 3 y, mediante un método similar, obtenemos A ≅ 235mod(252), donde A = 2503
  3. Y finalmente, al combinar esto con la ecuación 4, obtenemos A ≅ 1243mod(2772) donde A = 59455 y x = 1243

Observamos que 2772 es exactamente igual a 4 * 7 * 9 * 11. Así hemos encontrado el valor de x para la ecuación final. Puede consultar Algoritmo euclidiano extendido e Inverso multiplicativo modular para obtener información adicional sobre estos temas. 

C++

// C++ program to combine modular equations
// using Chinese Remainder Theorem
#include<bits/stdc++.h>
using namespace std;
 
// function that implements Extended euclidean
// algorithm
vector<int> extended_euclidean(int a,int b){
    if(a == 0){
        vector<int> temp;
        temp.push_back(b);
        temp.push_back(0);
        temp.push_back(1);
        return temp;
    }
    else{
        vector<int> temp(3);
        temp= extended_euclidean(b % a, a);
        int g = temp[0];
        int y = temp[1];
        int x = temp[2];
        temp[0] = g;
        temp[1] = x - ((b/a) * y);
        temp[2] = y;
        return temp;
    }
    vector<int> temp;
    return temp;
}
 
// modular inverse driver function
int modinv(int a,int m){
    vector<int> temp(3);
    temp = extended_euclidean(a, m);
    int g = temp[0];
    int x = temp[1];
    int y = temp[2];
     
    // Since we are taking the modulo of
    // negative numbers so, to have positive
    // output of the modulo we use this formula.
    int ans = x -  (floor(x/(float)m) * m);
    return ans;
}
     
 
// function implementing Chinese remainder theorem
// list m contains all the modulii
// list x contains the remainders of the equations
int crt(vector<int> &m,vector<int> & x)
{
   
    // We run this loop while the list of
    // remainders has length greater than 1
    while(1)
    {
       
        // temp1 will contain the new value
        // of A. which is calculated according
        // to the equation m1' * m1 * x0 + m0'
        // * m0 * x1
        int var1 = (modinv(m[1],m[0]));
        int var2 = (modinv(m[0],m[1]) );
        // cout << var1 << " " << var2 << endl;
        int temp1 = (modinv(m[1],m[0])) * x[0] * m[1] + (modinv(m[0],m[1]) )* x[1] * m[0];
 
        // temp2 contains the value of the modulus
        // in the new equation, which will be the
        // product of the modulii of the two
        // equations that we are combining
        int temp2 = m[0] * m[1];
        // cout << temp1<< " "<<temp2<< endl;
        // we then remove the first two elements
        // from the list of remainders, and replace
        // it with the remainder value, which will
        // be temp1 % temp2
        x.erase(x.begin());
        x.erase(x.begin());
        x.insert(x.begin(), temp1%temp2);
 
        //we then remove the first two values from
        //the list of modulii as we no longer require
        // them and simply replace them with the new
        // modulii that  we calculated
        m.erase(m.begin());
        m.erase(m.begin());
        m.insert(m.begin(), temp2);
 
        // once the list has only one element left,
        // we can break as it will only  contain
        // the value of our final remainder
        if(x.size()== 1){
            break;
        }
    }
         
    // returns the remainder of the final equation
    return x[0];
}
 
// driver segment
int main(){
    vector<int> m = {4, 7, 9, 11};
    vector<int> x = {3, 4, 1, 0};
    cout << crt(m, x) << endl;
    return 0;
}
 
// The code is contributed by Gautam goel (gautamgoe962)

Python

# Python 2.x program to combine modular equations
# using Chinese Remainder Theorem
 
# function that implements Extended euclidean
# algorithm
def extended_euclidean(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = extended_euclidean(b % a, a)
        return (g, x - (b // a) * y, y)
 
# modular inverse driver function
def modinv(a, m):
    g, x, y = extended_euclidean(a, m)
    return x % m
 
# function implementing Chinese remainder theorem
# list m contains all the modulii
# list x contains the remainders of the equations
def crt(m, x):
 
    # We run this loop while the list of
    # remainders has length greater than 1
    while True:
         
        # temp1 will contain the new value
        # of A. which is calculated according
        # to the equation m1' * m1 * x0 + m0'
        # * m0 * x1
        temp1 = modinv(m[1],m[0]) * x[0] * m[1] + \
                modinv(m[0],m[1]) * x[1] * m[0]
 
        # temp2 contains the value of the modulus
        # in the new equation, which will be the
        # product of the modulii of the two
        # equations that we are combining
        temp2 = m[0] * m[1]
 
        # we then remove the first two elements
        # from the list of remainders, and replace
        # it with the remainder value, which will
        # be temp1 % temp2
        x.remove(x[0])
        x.remove(x[0])
        x = [temp1 % temp2] + x
 
        # we then remove the first two values from
        # the list of modulii as we no longer require
        # them and simply replace them with the new
        # modulii that  we calculated
        m.remove(m[0])
        m.remove(m[0])
        m = [temp2] + m
 
        # once the list has only one element left,
        # we can break as it will only  contain
        # the value of our final remainder
        if len(x) == 1:
            break
 
    # returns the remainder of the final equation
    return x[0]
 
# driver segment
m = [4, 7, 9, 11]
x = [3, 4, 1, 0]
print crt(m, x)

Javascript

// JavaScript program to combine modular equations
// using Chinese Remainder Theorem
 
// function that implements Extended euclidean
// algorithm
function extended_euclidean(a, b){
    if(a == 0){
        let temp = [b, 0, 1];
        return temp;
    }
    else{
        let temp= extended_euclidean(b % a, a);
        let g = temp[0];
        let y = temp[1];
        let x = temp[2];
        temp[0] = g;
        temp[1] = x - (Math.floor(b/a) * y);
        temp[2] = y;
        return temp;
    }
    let temp;
    return temp;
}
 
// modular inverse driver function
function modinv(a, m){
    let temp = extended_euclidean(a, m);
    let g = temp[0];
    let x = temp[1];
    let y = temp[2];
     
    // Since we are taking the modulo of
    // negative numbers so, to have positive
    // output of the modulo we use this formula.
    let ans = x -  (Math.floor(x/m) * m);
    return ans;
}
     
 
// function implementing Chinese remainder theorem
// list m contains all the modulii
// list x contains the remainders of the equations
function crt(m, x)
{
   
    // We run this loop while the list of
    // remainders has length greater than 1
    while(1)
    {
       
        // temp1 will contain the new value
        // of A. which is calculated according
        // to the equation m1' * m1 * x0 + m0'
        // * m0 * x1
        let var1 = (modinv(m[1],m[0]));
        let var2 = (modinv(m[0],m[1]) );
        // cout << var1 << " " << var2 << endl;
        let temp1 = (modinv(m[1],m[0])) * x[0] * m[1] + (modinv(m[0],m[1]) )* x[1] * m[0];
 
        // temp2 contains the value of the modulus
        // in the new equation, which will be the
        // product of the modulii of the two
        // equations that we are combining
        let temp2 = m[0] * m[1];
        // cout << temp1<< " "<<temp2<< endl;
        // we then remove the first two elements
        // from the list of remainders, and replace
        // it with the remainder value, which will
        // be temp1 % temp2
        x.shift();
        x.shift();
        x.unshift(temp1 % temp2);
 
        //we then remove the first two values from
        //the list of modulii as we no longer require
        // them and simply replace them with the new
        // modulii that  we calculated
        m.shift();
        m.shift();
        m.unshift(temp2);
 
        // once the list has only one element left,
        // we can break as it will only  contain
        // the value of our final remainder
        if(x.length== 1){
            break;
        }
    }
         
    // returns the remainder of the final equation
    return x[0];
}
 
// driver segment
let m = [4, 7, 9, 11];
let x = [3, 4, 1, 0];
console.log(crt(m, x));
 
// The code is contributed by phasing17
Output
1243

Complejidad de tiempo: O(l), donde l es el tamaño de la lista restante.

Complejidad espacial: O (1), ya que no estamos utilizando ningún espacio adicional.

Este teorema y algoritmo tiene excelentes aplicaciones. Una aplicación muy útil es calcular n C r % m donde m no es un número primo y el teorema de Lucas no se puede aplicar directamente. En tal caso, podemos calcular los factores primos de m, y usar los factores primos uno por uno como módulo en nuestra ecuación n C r % m que podemos calcular usando el Teorema de Lucas, y luego combinar las ecuaciones resultantes usando el arriba se muestra el Teorema del Resto Chino. Este artículo es una contribución de Deepak Srivatsav . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.orgo envíe su artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks. Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *