logo

Bruke kinesisk restsetning for å kombinere modulære ligninger

Gitt N modulære ligninger: A ? x1mod(m1) . . A ? xnmod(mn) Finn x i ligningen A ? xmod(m1*m2*m3..*mn) hvor mjeger primtall eller potens av primtall og i tar verdier fra 1 til n. Inngangen er gitt som to matriser, den første er en matrise som inneholder verdier av hver xjegog den andre matrisen inneholder settet med verdier for hver primtall. mjegSkriv ut et heltall for verdien av x i den endelige ligningen. 

Eksempler: 

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

Forklaring: Vi tar sikte på å løse disse ligningene to om gangen. Vi tar de to første ligningene kombinerer det og bruker det resultatet til å kombinere med den tredje ligningen og så videre. Prosessen med å kombinere to ligninger er forklart som følger ved å ta eksempel 2 som referanse:



  1. A ? 3mod(4) og A ? 4mod(7) er de to ligningene som vi først er utstyrt med. La den resulterende ligningen være noe A? xmod(m1* m2).
    • ENer gitt av m1'*m1* x+ m'*m* x1hvor m1' = modulær invers av m1modul mog m' = modulær invers av mmodul m1
    • Vi kan beregne modulær invers ved å bruke utvidet euklidisk algoritme.
    • Vi finner xå være Amod (m1* m2)
    • Vi får vår nye ligning til å være A ? 11mod(28) der A er 95
  2. Vi prøver nå å kombinere dette med ligning 3 og ved en lignende metode får vi A ? 235mod(252) hvor A = 2503
  3. Og til slutt ved å kombinere dette med ligning 4 får vi A ? 1243mod(2772) der A = 59455 og x = 1243

Vi observerer at 2772 med rette er lik 4 * 7 * 9 * 11. Vi har dermed funnet verdien av x for den endelige ligningen. Du kan henvise til Utvidet euklidisk algoritme og Modulær multiplikativ invers for ekstra informasjon om disse emnene. 

C++
// C++ program to combine modular equations // using Chinese Remainder Theorem #include   using namespace std; // function that implements Extended euclidean // algorithm vector<int> extended_euclidean(int aint 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 aint 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> &mvector<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<< ' '<  // 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) 
Java
// Java program to implement the Chinese Remainder Theorem import java.util.ArrayList; import java.math.BigInteger; public class ChineseRemainderTheorem {  // Function to calculate the modular inverse of a and m  public static BigInteger modinv(BigInteger a BigInteger m) {  BigInteger m0 = m;  BigInteger y = BigInteger.ZERO;  BigInteger x = BigInteger.ONE;  if (m.equals(BigInteger.ONE))  return BigInteger.ZERO;  while (a.compareTo(BigInteger.ONE) == 1) {  BigInteger q = a.divide(m);  BigInteger t = m;  m = a.mod(m);  a = t;  t = y;  y = x.subtract(q.multiply(y));  x = t;  }  if (x.compareTo(BigInteger.ZERO) == -1)  x = x.add(m0);  return x;  }  // Function to implement the Chinese Remainder Theorem  public static BigInteger crt(ArrayList<BigInteger> m ArrayList<BigInteger> x) {  BigInteger M = BigInteger.ONE;  for (int i = 0; i < m.size(); i++) {  M = M.multiply(m.get(i));  }  BigInteger result = BigInteger.ZERO;  for (int i = 0; i < m.size(); i++) {  BigInteger Mi = M.divide(m.get(i));  BigInteger MiInv = modinv(Mi m.get(i));  result = result.add(x.get(i).multiply(Mi).multiply(MiInv));  }  return result.mod(M);  }  public static void main(String[] args) {  ArrayList<BigInteger> m = new ArrayList<>();  ArrayList<BigInteger> x = new ArrayList<>();  m.add(BigInteger.valueOf(4));  m.add(BigInteger.valueOf(7));  m.add(BigInteger.valueOf(9));  m.add(BigInteger.valueOf(11));  x.add(BigInteger.valueOf(3));  x.add(BigInteger.valueOf(4));  x.add(BigInteger.valueOf(1));  x.add(BigInteger.valueOf(0));  System.out.println(crt(m x));  } } // This code is contributed by Vikram_Shirsat 
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) 
C#
using System; using System.Collections; using System.Collections.Generic; using System.Linq; // C# program to combine modular equations // using Chinese Remainder Theorem class HelloWorld {  // function that implements Extended euclidean  // algorithm  public static List<int> extended_euclidean(int aint b){  if(a == 0){  List<int> temp = new List<int>();  temp.Add(b);  temp.Add(0);  temp.Add(1);   return temp;  }  else{  List<int> temp = new List<int>();  temp.Add(0);  temp.Add(0);  temp.Add(0);  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;  }  List<int> temp1 = new List<int>();  return temp1;  }  // modular inverse driver function  public static double modinv(int aint m){  List<int> temp = new List<int>();  temp.Add(0);  temp.Add(0);  temp.Add(0);  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.   double val = Math.Floor(((double)x/(double)m));  double ans = x - (val * m);  return ans;  }  // function implementing Chinese remainder theorem  // list m contains all the modulii  // list x contains the remainders of the equations  public static int crt(List<int> mList<int> 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  double var1 = (modinv(m[1]m[0]));  double var2 = (modinv(m[0]m[1]));  // cout << var1 << ' ' << var2 << endl;  double 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<< ' '<  // 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.RemoveAt(0);  x.RemoveAt(0);  x.Insert(0 (int)temp1%(int)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.RemoveAt(0);  m.RemoveAt(0);  m.Insert(0 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.Count == 1){  break;  }  }  // returns the remainder of the final equation  return x[0];  }  static void Main() {  List<int> m = new List<int>(){  4 7 9 11  };  List<int> x = new List<int> (){  3 4 1 0  };  Console.WriteLine(crt(m x));  } } // The code is contributed by Nidhi goel.  
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<< ' '<  // 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 

Produksjon:

1243

Tidskompleksitet: O(l) hvor l er størrelsen på restlisten.

Plass kompleksitet: O(1) da vi ikke bruker noe ekstra plass.

Denne teoremet og algoritmen har utmerkede applikasjoner. En veldig nyttig applikasjon er å beregnenCr% m hvor m ikke er et primtall og Lucas teorem kan ikke brukes direkte. I et slikt tilfelle kan vi beregne primfaktorene til m og bruke primfaktorene en etter en som en modul i vårnCr% m-ligningen som vi kan beregne ved å bruke Lucas-teorem og deretter kombinere de resulterende ligningene ved å bruke den ovenfor viste kinesiske restsetningen.

Lag quiz