中国剩余定理
中国剩余定理
中国剩余定理,CRT是用来求多组同余方程的解,前提是模数
m
i
m_i
mi两两互质
f
(
x
)
=
{
x
≡
a
1
(
m
o
d
m
1
)
x
≡
a
2
(
m
o
d
m
2
)
x
≡
a
3
(
m
o
d
m
3
)
.
.
.
x
≡
a
k
(
m
o
d
m
k
)
f(x)=\left\{ \begin{aligned} x \equiv a_1 \pmod {m_1}\\ x \equiv a_2 \pmod{m_2}\\ x \equiv a_3 \pmod{m_3}\\ ...\\ x \equiv a_k \pmod{m_k}\\ \end{aligned} \right.
f(x)=⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧x≡a1(modm1)x≡a2(modm2)x≡a3(modm3)...x≡ak(modmk)
设
M
=
[
m
1
,
m
2
,
m
3
,
.
.
.
,
m
k
]
=
∏
i
=
1
k
m
i
M=[m_1,m_2,m_3,...,m_k]=\prod_{i=1}^km_i
M=[m1,m2,m3,...,mk]=∏i=1kmi ,
m
k
i
=
M
m
i
mk_i=\frac{M}{m_i}
mki=miM
且
t
i
t_i
ti是同余方程
m
k
i
∗
t
i
≡
1
(
m
o
d
m
i
)
mk_i*t_i\equiv 1 \pmod{m_i}
mki∗ti≡1(modmi)的最小非负整数解
一、
因为对于任意 j j j ≠ \ne ̸= i i i , m k i ≡ 0 ( m o d m j ) mk_i \equiv 0 \pmod{m_j} mki≡0(modmj)
所以 m k i ∗ a i ∗ t i ≡ 0 ( m o d m j ) mk_i*a_i*t_i \equiv 0 \pmod{m_j} mki∗ai∗ti≡0(modmj)
又因为 m k i ∗ t i ≡ 1 ( m o d m i ) mk_i*t_i\equiv 1 \pmod{m_i} mki∗ti≡1(modmi)
所以 m k i ∗ t i ∗ a i ≡ a i ( m o d m i ) mk_i*t_i*a_i\equiv a_i \pmod{m_i} mki∗ti∗ai≡ai(modmi)
二、
所以对于任意 j j j ≠ \ne ̸= i i i , m k j ∗ a j ∗ t j ≡ 0 ( m o d m i ) mk_j*a_j*t_j \equiv 0 \pmod{m_i} mkj∗aj∗tj≡0(modmi)
所以 m k j ∗ a j ∗ t j + m k i ∗ t i ∗ a i ≡ a i ( m o d m i ) mk_j*a_j*t_j + mk_i*t_i*a_i \equiv a_i \pmod{m_i} mkj∗aj∗tj+mki∗ti∗ai≡ai(modmi)
把所有 j j j ≠ \ne ̸= i i i 的式子求和,再与 m k i ∗ t i ∗ a i mk_i*t_i*a_i mki∗ti∗ai 求和,
得到 ∑ i = 1 k m k i ∗ t i ∗ a i = x \sum_{i=1}^k mk_i*t_i*a_i=x ∑i=1kmki∗ti∗ai=x的一组特解
通解为 x + i ∗ M ( i ∈ Z ) x+i*M(i\in Z) x+i∗M(i∈Z)
扩展中国剩余定理
模数
m
i
m_i
mi为不一定两两互质的整数
求x的最小非负整数解
假设已经求出前k-1个方程组成的同余方程组的一个解为x
且有
M
=
∏
i
−
1
k
−
1
m
i
M=\prod_{i-1}^{k-1}m_i
M=∏i−1k−1mi
则前k-1个方程的方程组通解为
x
+
i
∗
M
(
i
∈
Z
)
x+i*M(i\in Z)
x+i∗M(i∈Z)
那么对于加入第
k
k
k个方程后的方程组
我们就是要求一个正整数
t
t
t,使得
x
+
t
∗
M
≡
a
(
m
o
d
m
k
)
x+t ∗ M≡a\pmod {m_k}
x+t∗M≡a(modmk)
转化一下上述式子得
t
∗
M
≡
a
k
−
x
(
m
o
d
m
k
)
t∗M≡a_k-x \pmod{m_k}
t∗M≡ak−x(modmk)
M
∗
t
+
m
k
∗
p
=
a
k
−
x
M*t+m_k*p=a_k-x
M∗t+mk∗p=ak−x ——①
设
g
=
(
M
,
m
k
)
g=(M,m_k)
g=(M,mk)
解
M
∗
t
+
m
k
∗
p
=
g
M*t+m_k*p =g
M∗t+mk∗p=g,得到答案
t
0
t_0
t0
要模b/gcd是因为要求出通解中的最小解
对于这个式子我们已经可以通过扩展欧几里得求解
t
t
t
若该同余式无解,则整个方程组无解
若有,则前k个同余式组成的方程组的一个解,解为
x
k
=
x
+
t
∗
M
x_k=x+t*M
xk=x+t∗M
所以整个算法的思路就是求解k次扩展欧几里得
#include <bits/stdc++.h>
#define ll long long
#define MAX 100005
using namespace std;
ll n, m, ans;
ll a[MAX], b[MAX];
ll exgcd(ll a, ll b, ll &x, ll &y){
if(!b){
x = 1, y = 0;
return a;
}
ll res = exgcd(b, a%b, x, y);
ll t = x;
x = y, y = t-a/b*y;
return res;
}
ll mul(ll a, ll b, ll mod){
ll res = 0, base = a;
while(b){
if(b&1){
res = (res+base)%mod;
}
base = (base+base)%mod;
b >>= 1;
}
return res;
}
ll excrt(){
m = b[1], ans = a[1];
for(int i = 2; i <= n; i++){
ll p = ((a[i]-ans)%b[i]+b[i])%b[i];
ll x, y; //mx=p (mod b[i])
ll gcd = exgcd(m, b[i], x, y);
if(p % gcd) return -1;
x = mul(x, p/gcd, b[i]/gcd);
ans += x*m;
m *= b[i]/gcd;
ans = (ans%m+m)%m;
}
return (ans%m+m)%m;
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++){
scanf("%lld%lld", &b[i], &a[i]);
}
printf("%lld\n", excrt());
return 0;
}
t ∗ M ≡ a k − x ( m o d m k ) t∗M≡a_k-x \pmod{m_k} t∗M≡ak−x(modmk)
d = ( M , m k ) d= (M,m_k) d=(M,mk)
t ∗ M ≡ d ( m o d m k ) t∗M≡d \pmod{m_k} t∗M≡d(modmk)