Advertisement
RaFiN_

CRT

Jul 9th, 2019
274
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.03 KB | None | 0 0
  1. /**
  2.     A CRT solver which works even when moduli are not pairwise coprime
  3.  
  4.     1. Add equations using addEquation() method
  5.     2. Call solve() to get {x, N} pair, where x is the unique solution modulo N.
  6.  
  7.     Assumptions:
  8.         1. LCM of all mods will fit into long long.
  9. */
  10. class ChineseRemainderTheorem {
  11.     typedef long long vlong;
  12.     typedef pair<vlong,vlong> pll;
  13.  
  14.     /** CRT Equations stored as pairs of vector. See addEqation()*/
  15.     vector<pll> equations;
  16.  
  17. public:
  18.     void clear() {
  19.         equations.clear();
  20.     }
  21.  
  22.  
  23.     vlong ext_gcd ( vlong A, vlong B, vlong *X, vlong *Y ){
  24.     vlong x2, y2, x1, y1, x, y, r2, r1, q, r;
  25.     x2 = 1; y2 = 0;
  26.     x1 = 0; y1 = 1;
  27.     for (r2 = A, r1 = B; r1 != 0; r2 = r1, r1 = r, x2 = x1, y2 = y1, x1 = x, y1 = y ) {
  28.         q = r2 / r1;
  29.         r = r2 % r1;
  30.         x = x2 - (q * x1);
  31.         y = y2 - (q * y1);
  32.     }
  33.     *X = x2; *Y = y2;
  34.     return r2;
  35. }
  36.  
  37.     /** Add equation of the form x = r (mod m)*/
  38.     void addEquation( vlong r, vlong m ) {
  39.         equations.push_back({r, m});
  40.     }
  41.     pll solve() {
  42.         if (equations.size() == 0) return {-1,-1}; /// No equations to solve
  43.  
  44.         vlong a1 = equations[0].first;
  45.         vlong m1 = equations[0].second;
  46.         a1 %= m1;
  47.         /** Initially x = a_0 (mod m_0)*/
  48.  
  49.         /** Merge the solution with remaining equations */
  50.         for ( int i = 1; i < equations.size(); i++ ) {
  51.             vlong a2 = equations[i].first;
  52.             vlong m2 = equations[i].second;
  53.  
  54.             vlong g = __gcd(m1, m2);
  55.             if ( a1 % g != a2 % g ) return {-1,-1}; /// Conflict in equations
  56.  
  57.             /** Merge the two equations*/
  58.             vlong p, q;
  59.             ext_gcd(m1/g, m2/g, &p, &q);
  60.  
  61.             vlong mod = m1 / g * m2;
  62.             vlong x = ( (__int128)a1 * (m2/g) % mod *q % mod + (__int128)a2 * (m1/g) % mod * p % mod ) % mod;
  63.  
  64.             /** Merged equation*/
  65.             a1 = x;
  66.             if ( a1 < 0 ) a1 += mod;
  67.             m1 = mod;
  68.         }
  69.         return {a1, m1};
  70.     }
  71. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement