1635:【例 5】Strange Way to Express Integers
题目描述
给定 2n 个正整数 a1,a2,⋯,an 和 m1,m2,⋯,mn,求一个最小的正整数 x,满足 ∀i∈[1,n],x≡ai(modmi),或者给出无解。
输入格式
多组数据。
每组数据第一行一个整数 n;
接下来 n 行,每行两个整数 mi,ai。
输出格式
对于每组数据,若无解,输出 −1;否则输出一个非负整数,若有多解,输出最小的满足条件的答案。
样例
样例输入 #1
2
8 7
11 9
样例输出 #1
31
样例解释 #1
- n=2,两个方程:
- x≡7(mod8)
- x≡9(mod11)
- 最小的正整数解 x=31(因为 31mod8=7,31mod11=9)。
数据范围
对于全部数据:
- 所有的输入都是非负的,并且可以用 64 位有符号整数表示。
- 保证 1≤n≤105,mi>ai。
时空限制
- 时间限制:1000 ms
- 内存限制:524288 KB
注意:本题是扩展中国剩余定理(ExCRT)的模板题。与普通中国剩余定理不同,这里的模数 mi 不一定两两互质。因此需要使用扩展中国剩余定理求解同余方程组。
扩展中国剩余定理的核心思想是逐步合并同余方程。考虑两个方程:
$$\begin{cases}
x \equiv a_1 \pmod{m_1} \\
x \equiv a_2 \pmod{m_2}
\end{cases}$$
这等价于存在整数 k1,k2 使得:
x=a1+m1k1=a2+m2k2
移项得:
m1k1−m2k2=a2−a1
这是一个线性丢番图方程。设 d=gcd(m1,m2),方程有解当且仅当 d∣(a2−a1)。如果无解,则整个方程组无解。
如果有解,可以用扩展欧几里得算法求出 k1 的一个特解 k1′,则通解为:
k1=k1′+dm2t
其中 t 是任意整数。代入 x=a1+m1k1 得:
$$x = a_1 + m_1 \left( k_1' + \frac{m_2}{d} t \right) = (a_1 + m_1 k_1') + \frac{m_1 m_2}{d} t$$
这表示 x 可以写成 x≡x0(modM) 的形式,其中 x0=a1+m1k1′,M=lcm(m1,m2)=dm1m2。
因此,我们将两个方程合并为一个新的方程 x≡x0(modM)。重复这个过程,直到合并所有方程,最后得到 x≡x0(modM),最小正整数解为 x0modM(如果 x0 为负数,调整到 [0,M−1])。
算法步骤(对于每组数据):
- 初始化 x0=0, M=1(表示当前解为 x≡0(mod1),即任意整数)。
- 依次读入每个 (mi,ai),设当前方程为 x≡ai(modmi)。
- 合并方程 x≡x0(modM) 和 x≡ai(modmi):
- 计算 d=gcd(M,mi)。
- 如果 (ai−x0) 不能被 d 整除,则无解,输出 −1。
- 否则,用扩展欧几里得算法求 p,q 使得 pM+qmi=d。
- 计算 k=(ai−x0)/d。
- 计算新的 x0=x0+M⋅p⋅k(注意可能溢出,需要取模新模数)。
- 计算新的 M=lcm(M,mi)=M/d∗mi。
- 调整 x0 为正且小于 M:x0=(x0modM+M)modM。
- 合并完所有方程后,输出 x0(即最小非负整数解)。
注意:由于 mi,ai 可以用 64 位有符号整数表示,计算过程中可能溢出,需要使用 __int128 或快速乘来避免溢出。例如,计算 M⋅p⋅k 可能超过 long long 范围,可以先用 __int128 计算再取模,或者使用快速乘(龟速乘)在取模意义下计算。
由于 n≤105,需要高效实现,但扩展欧几里得算法是 O(logmin(M,mi)),总复杂度 O(nlogM),可以接受。
注意多组数据,直到 EOF。