给定
n
n
n 个正整数
a
i
a_i
ai 和
n
n
n 个非负整数
b
i
b_i
bi,求解关于
x
x
x 的线性同余方程组:
{
x
≡
b
1
(
m
o
d
a
1
)
x
≡
b
2
(
m
o
d
a
2
)
⋯
x
≡
b
n
(
m
o
d
a
n
)
\begin{cases} x\equiv b_1\pmod {a_1}\\ x\equiv b_2\pmod {a_2}\\ \cdots\\ x\equiv b_n\pmod {a_n}\\ \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧x≡b1(moda1)x≡b2(moda2)⋯x≡bn(modan)
其中
∀
i
,
j
∈
[
1
,
n
]
,
i
≠
j
\forall i,j\in[1,n],i\ne j
∀i,j∈[1,n],i=j 满足
a
i
,
a
j
a_i,a_j
ai,aj 互质。
首先令 m = ∏ i = 1 n a i m=\prod\limits_{i=1}^{n}a_i m=i=1∏nai。
如果有一个解 x 1 x_1 x1,那么通解就是 x = x 1 + t m x=x_1+tm x=x1+tm( t t t 为整数)。
所以我们只需要求出最小解即可,那么这个最小解一定 < m < m <m。
中国剩余定理( C h i n e s e R e m a i n d e r T h e o r e m , C R T \rm Chinese\ Remainder\ Theorem, CRT Chinese Remainder Theorem,CRT)给出了构造解的方法:
x = ( ∑ i = 1 n b i m i M i ) m o d m x=(\sum\limits_{i=1}^n b_im_iM_i)\bmod m x=(i=1∑nbimiMi)modm
其中 m i = m a i m_i=\dfrac{m}{a_i} mi=aim, M i M_i Mi 为 m i m_i mi 在模 a i a_i ai 意义下的逆元。
则
∀
i
,
j
∈
[
1
,
n
]
,
i
≠
j
\forall i,j\in[1,n],i\ne j
∀i,j∈[1,n],i=j:
b
j
m
j
M
j
≡
b
j
m
a
j
M
j
≡
b
j
a
1
a
2
⋯
a
i
⋯
a
n
a
j
M
j
≡
b
j
⋅
0
⋅
M
j
≡
0
(
m
o
d
a
i
)
\begin{aligned} b_jm_jM_j &\equiv b_j\dfrac{m}{a_j}M_j\\ &\equiv b_j\dfrac{a_1 a_2\cdots a_i\cdots a_n}{a_j}M_j\\ &\equiv b_j\cdot 0\cdot M_j\\ &\equiv 0 \pmod {a_i} \end{aligned}
bjmjMj≡bjajmMj≡bjaja1a2⋯ai⋯anMj≡bj⋅0⋅Mj≡0(modai)
而
∀
i
∈
[
1
,
n
]
\forall i\in[1,n]
∀i∈[1,n]:
b
i
m
i
M
i
≡
b
i
(
m
i
M
i
)
≡
b
I
(
m
i
m
i
−
1
)
≡
b
i
⋅
1
≡
b
i
(
m
o
d
a
i
)
\begin{aligned} b_im_iM_i &\equiv b_i(m_iM_i)\\ &\equiv b_I(m_im_i^{-1})\\ &\equiv b_i\cdot 1\\ &\equiv b_i \pmod {a_i} \end{aligned}
bimiMi≡bi(miMi)≡bI(mimi−1)≡bi⋅1≡bi(modai)
所以
∀
i
∈
[
1
,
n
]
\forall i\in[1,n]
∀i∈[1,n]:
∑
i
=
1
n
b
i
m
i
M
i
≡
∑
j
=
1
,
j
≠
i
n
b
j
m
j
M
j
+
b
i
m
i
M
i
≡
0
+
b
i
≡
b
i
(
m
o
d
a
i
)
\begin{aligned} \sum\limits_{i=1}^n b_im_iM_i &\equiv \sum\limits_{j=1,j\ne i}^n b_jm_jM_j+b_im_iM_i\\ &\equiv 0+b_i\\ &\equiv b_i \pmod {a_i} \end{aligned}
i=1∑nbimiMi≡j=1,j=i∑nbjmjMj+bimiMi≡0+bi≡bi(modai)
这就是一组满足条件的解了。
接下来证明在模 m m m 的意义下只有一个解。
假设有 x ≡ y ( m o d m ) x\equiv y\pmod m x≡y(modm),那么 ∀ i ∈ [ 1 , n ] \forall i\in[1,n] ∀i∈[1,n],有
x ≡ x m o d m ≡ y ( m o d a i ) \begin{aligned}x &\equiv x\bmod m\\ &\equiv y \pmod {a_i} \end{aligned} x≡xmodm≡y(modai)
所以 x x x 和 y y y 是同一个解。
时间复杂度为 O ( n log n ) \mathcal{O}(n\log n) O(nlogn)。
Code \text{Code} Code
//18 = 9 + 9 = 18.
#include <iostream>
#include <cstdio>
typedef long long ll;
using namespace std;
const int MAXN = 15;
ll x, y;
void exgcd(ll a, ll b)
{
if (!b)
{
x = 1, y = 0;
return;
}
exgcd(b, a % b);
ll tmp = x;
x = y;
y = tmp - a / b * y;
}
ll inv(ll a, ll p)
{
exgcd(a, p);
x = (x % p + p) % p;
return x;
}
ll qmul(ll a, ll b, ll p)
{
ll base = a, ans = 0;
while (b)
{
if (b & 1)
{
ans = (ans + base) % p;
}
base = (base + base) % p;
b >>= 1;
}
return ans;
}
int a[MAXN], b[MAXN];
ll CRT(int n)
{
ll m = 1;
for (int i = 1; i <= n; i++)
{
m *= a[i];
}
ll ans = 0;
for (int i = 1; i <= n; i++)
{
ll mi = m / a[i];
ll Mi = inv(mi, a[i]);
ans = (ans + qmul(b[i], qmul(mi, Mi, m), m)) % m;
}
return ans;
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d%d", a + i, b + i);
}
printf("%lld\n", CRT(n));
return 0;
}
双倍经验:P3868 [TJOI2009] 猜数字