对于每两个式子(我们考虑将其合并):
{ x ≡ a 1 ( % m 1 ) x ≡ a 2 ( % m 2 ) \left\{ \begin{array}{c} x≡a_1(\% m_1)\\ x≡a_2(\% m_2) \end{array} \right. {x≡a1(%m1)x≡a2(%m2)
则有:
{ x = a 1 + k 1 ∗ m 1 x = a 2 + k 2 ∗ m 2 \left\{ \begin{array}{c} x = a_1 + k_1 * m_1\\ x = a_2 + k_2 * m_2 \end{array} \right. {x=a1+k1∗m1x=a2+k2∗m2
两式合并:
a 1 + k 1 ∗ m 1 = a 2 + k 2 ∗ m 2 a_1 + k_1 * m_1 = a_2 + k_2 * m_2 a1+k1∗m1=a2+k2∗m2
移项得: k 1 ∗ m 1 + ( − k 2 ) ∗ m 2 = a 2 − a 1 k_1 * m_1 + (-k_2) * m_2 = a_2 - a_1 k1∗m1+(−k2)∗m2=a2−a1 (由扩展欧几里得算法解得 k 1 ′ k_1^′ k1′, k 2 ′ k_2^′ k2′)
k 1 k_1 k1的通解为: k 1 = k 1 ′ + k ∗ m 2 g c d ( m 1 , m 2 ) k_1 = k_1^′ + k * \frac{m_2}{gcd(m_1 , m_2)} k1=k1′+k∗gcd(m1,m2)m2
k 1 k_1 k1的通解的求法:利用二元不定方程组的通解
例:将 − k 2 -k_2 −k2 看成 k 2 k_2 k2, m 1 , m 2 m_1,m_2 m1,m2 的最大公倍数用 d d d 表示。k 1 ∗ m 1 + k 2 ∗ m 2 = a 2 − a 1 k_1 * m_1 + k_2 * m_2 = a_2 - a_1 k1∗m1+k2∗m2=a2−a1
k 1 ′ ∗ m 1 + k 2 ′ ∗ m 2 = a 2 − a 1 k_1^′ * m_1 + k_2^′ * m_2 = a_2 - a_1 k1′∗m1+k2′∗m2=a2−a1
两式相减
( k 1 − k 1 ′ ) ∗ m 1 = ( k 2 − k 2 ′ ) ∗ m 2 (k_1 - k_1^′ ) * m_1 = (k_2 - k_2^′ ) * m_2 (k1−k1′)∗m1=(k2−k2′)∗m2
两边同时约掉最大公倍数 d d d 为:(目的使 m 1 , m 2 m_1,m_2 m1,m2 互质)
不约掉时:设 k = k 1 − k 1 ′ , d = 2 k = k_1 - k_1^′ ,d = 2 k=k1−k1′,d=2 相当与给 k k k 乘 2 2 2 此时 ( k ∗ 2 ) (k*2) (k∗2) 只能取偶数,不为全部解。( k 1 − k 1 ′ ) ∗ m 1 d = ( k 2 − k 2 ′ ) ∗ m 2 d (k_1 - k_1^′ ) * \frac{m_1}{d} = (k_2 - k_2^′ ) * \frac{m_2}{d} (k1−k1′)∗dm1=(k2−k2′)∗dm2
解得:
k 1 = k 1 ′ + k ∗ m 2 d k_1 = k_1^′ + k * \frac{m_2}{d} k1=k1′+k∗dm2
k 2 = k 2 ′ + k ∗ m 1 d k_2 = k_2^′ + k * \frac{m_1}{d} k2=k2′+k∗dm1
将 k 1 k_1 k1 带入 x = a 1 + k 1 ∗ m 1 x = a_1 + k_1 * m_1 x=a1+k1∗m1 中,即为 x x x 的通解 x = ( k 1 ′ ∗ m + a 1 ) + k ∗ m 1 m 2 g c d ( m 1 , m 2 ) x = (k_1^′ * m + a_ 1)+ k * \frac{m_1m_2}{gcd(m_1 , m_2)} x=(k1′∗m+a1)+k∗gcd(m1,m2)m1m2
typedef long long ll;
ll exgcd(ll a, ll b, ll& x, ll& y)
{
if (!b)
{
x = 1, y = 0;
return a;
}
ll d = exgcd(b, a % b, x, y);
ll t = y;
y = x - a / b * y;
x = t;
return d;
}
int main()
{
int n; cin >> n;
ll a1, m1; cin >> m1 >> a1;
bool flag = true;
for (int i = 0; i < n - 1; i++)
{
ll a2, m2; cin >> m2 >> a2;
ll k1, k2;
ll d = exgcd(m1, m2, k1, k2);
if ((a2 - a1) % d) // 判断是否有解
{
flag = false;
break;
}
k1 *= (a2 - a1) / d;
ll t = m2 / d;
k1 = (k1 % t + t) % t; //k1 = k1 + k * t 均为k1的解,取最小的一个
a1 = k1 * m1 + a1;
m1 = m1 / d * m2;
}
if (flag) cout << (a1 % m1 + m1) % m1 << endl;
else puts("-1");
}