題目來源:2019牛客暑期多校訓練營(第十場)oop
看標題就知道大概了,韓信點兵的典故咱們應該都熟悉吧。 給出 $n$ 個同餘方程,問是否存在不超過 $m$ 的正整數解。
ui
數據比較大,直接用 CRT 會爆 ll,這時候就用 Python 來實現。 spa
n = 110 # 同餘方程個數 a = [0]*110 # 餘數 m = [0]*110 # 模數 """擴展歐幾里得""" def exgcd(a, b): if 0 == b: return 1, 0, a x, y, q = exgcd(b, a % b) x, y = y, (x - a // b * y) return x, y, q """擴展中國剩餘定理""" def CRT(): if n == 1 : if m[0] > a[0]: return a[0]; else: return -1; for i in range(n): if m[i] <= a[i] : return -1; x, y, d = exgcd(m[0], m[i]) if (a[i] - a[0]) % d != 0: return -1; t = m[i] // d; x = (a[i] - a[0]) // d * x % t a[0] = x * m[0] + a[0]; m[0] = m[0] * m[i] // d; a[0] = (a[0] % m[0] + m[0]) % m[0] return a[0]; n, k = map(int, input().split()) for i in range(n): m[i], a[i] = map(int, input().split()) ans = CRT() if ans==-1: print("he was definitely lying") elif ans<=k: print(ans) else : print("he was probably lying")
PS:擴展中國剩餘定理彷佛與中國剩餘定理(CRT)關係不大,如下給出推導過程。 對於一組同餘方程 $$ \begin{cases} {x} \equiv {a_1} \text{ mod } {m_1}\ {x} \equiv {a_2} \text{ mod } {m_2}\ \dots\\ {x} \equiv {a_n} \text{ mod } {m_n}\ \end{cases}$$code
咱們經過依次合併兩組方程獲得新的同餘方程,這樣通過 $n-1$ 次操做後,就能獲得方程組的解。get
首先對於前兩組方程有: $$ {x = a_1 + k_1m_1}\ {x= a_2 + k_2m_2}$$ 可得 $${k_1m_1 - k_2m_2 = a_2-a_1}$$ 由擴展歐幾里得,咱們能夠獲得下面方程的解 ${x_0, y_0}$ $$ {x_0m_1 - y_0m_2 = (m_1, m_2)}$$ 設 ${d = (m_1, m_2)}$ 當且僅當 ${(a_2-a_1)} \text{ mod } {d = 0}$,方程有解。input
因此 $$ {x_0\frac{ a_2-a_1}{d}m_1 - y_0\frac{ a_2-a_1}{d}m_2 = a_2-a_1}$$ 因此咱們獲得 $k_1$ 的一組解爲 $$k_1 = x_0\frac{ a_2-a_1}{d}$$ 方程的通解形式爲 $$k_1 = k_1+n\frac{m_2}{d}\ k_2 = k_2-n\frac{m_1}{d}$$ $k_1$ 的最小整數解爲 $$k_1 = k_1\text{ mod } (m_2/d)$$it
代回原方程 $x = a_1+k_1n_1 $,咱們獲得 $x$ 的解以及 $a$. 此時方程組合並後的模數爲 $$ M = m_1*m_2/d$$ 所以原方程合併爲 $$ {x} = {a}\text{ mod } {M}$$ io