Yukicoder No.187 中華風 (Hard)
CRTはCTFのcrypto問で使うからライブラリにあるんですよと言いながらNo.186 中華風 (Easy)を解いたら、そのままこちらも解けていた。
solution
中国人剰余定理ほぼそのまま。 ただし法$M_i$が互いに素とは限らないのでいい感じにし、$10^9+7$での剰余は最後にのみ取る。 整数演算を定数時間と見て$O(N)$だが、桁数は$O(N\log_{10}(\max Y_i))$ (この問題の制約では最大で$10$進$9000$桁)となる。
implementation
#!/usr/bin/env python3
import functools
import math
lcm = lambda a, b: a * b // math.gcd(a, b)
def extgcd(a, b):
if b == 0:
return 1, 0
else:
na, nb = extgcd(b, a % b)
return nb, na - a//b * nb
def modinv(a, n):
return extgcd(a, n)[0] % n
def crt(eqn1, eqn2):
x1, m1 = eqn1
x2, m2 = eqn2
d = math.gcd(m1, m2)
x = x1 + (m1 // d) * (x2 - x1) * modinv(m1 // d, m2 // d)
m = lcm(m1, m2)
return x % m, m
n = int(input())
eqn = [ tuple(map(int, input().split())) for _ in range(n) ]
ans, _ = functools.reduce(crt, eqn)
if ans == 0:
ans += functools.reduce(lcm, map(lambda it: it[1], eqn))
for x, y in eqn:
if ans % y != x:
ans = -1
break
else:
ans %= 10**9+7
print(ans)