def crt(a, m): # Return (x, l) such that x = a[i] mod m[i] (-1 if no solution) and l = lcm(m) # Pre: a[i], m[i] >= 0 for all i # Post: x = a[i] mod m[i] for all i, 0 <= x < l, l = lcm(m) (x = -1 if no solution) x0, m0 = 0, 1 for i in range(len(m)): x0, m0 = gauss(x0, m0, a[i], m[i]), lcm(m0, m[i]) if x0 == -1: break return (x0, m0)
def gauss(a1, m1, a2, m2): # Return x such that x = a1 mod m1, x = a2 mod m2 (-1 if no solution) # Pre: a1, a2, m1, m2 >= 0 # Post: x = a1 mod m1, x = a2 mod m2, 0 <= x < lcm(m1, m2) (x = -1 if no solution) d = gcd(m1, m2) if a1 % d != a2 % d: return -1 if a1 > a2: a1, m1, a2, m2 = a2, m2, a1, m1 t1 = lin_solve(m1//d, (a2-a1)//d % (m2//d), m2//d) # See Bach-Shallit p.116 return (a1 + t1 * m1) % lcm(m1, m2)