题意: 给定
n
n
n个整数
a
1
,
a
2
,
.
.
.
,
a
n
a_1,a_2,...,a_n
a1,a2,...,an和
n
n
n个整数
m
1
,
m
2
,
.
.
.
m
n
m_1,m_2,...m_n
m1,m2,...mn,
∀
i
∈
[
1
,
n
]
,
x
≡
m
i
(
m
o
d
a
i
)
\forall i\in[1,n],x\equiv m_i\pmod {a_i}
∀i∈[1,n],x≡mi(modai)。求存在的最小
x
x
x
题解:
依次合并每个同余式。
下面以两个同余式为例:
x
≡
m
1
(
m
o
d
a
1
)
x\equiv m_1\pmod {a_1}
x≡m1(moda1)
x
≡
m
2
(
m
o
d
a
2
)
x\equiv m_2\pmod {a_2}
x≡m2(moda2)
等价于:
x
=
a
1
k
1
+
m
1
x=a_1k_1+m_1
x=a1k1+m1 ①
x
=
a
2
k
2
+
m
2
x=a_2k_2+m_2
x=a2k2+m2 ②
联立可得:
a
1
k
1
+
m
1
=
a
2
k
2
+
m
2
a_1k_1+m_1=a_2k_2+m_2
a1k1+m1=a2k2+m2
移项得:
a
1
k
1
−
a
2
k
2
=
m
2
−
m
1
a_1k_1-a_2k_2=m_2-m_1
a1k1−a2k2=m2−m1
可以看出来是
e
x
g
c
d
exgcd
exgcd的标准形式,故有解的条件是
g
c
d
(
a
1
,
a
2
)
∣
(
m
2
−
m
1
)
gcd(a_1,a_2)\mid(m_2-m_1)
gcd(a1,a2)∣(m2−m1)
目标为消去不定因素
k
1
,
k
2
k_1,k_2
k1,k2
设
d
=
g
c
d
(
a
1
,
a
2
)
d=gcd(a1,a2)
d=gcd(a1,a2)
两边同除
d
d
d得:
a
1
d
k
1
−
a
2
d
k
2
=
m
2
−
m
1
d
\frac{a_1}{d}k_1-\frac{a_2}{d}k_2=\frac{m_2-m_1}{d}
da1k1−da2k2=dm2−m1
等价于:
a
1
d
k
1
≡
m
2
−
m
1
d
(
m
o
d
a
2
d
)
\frac{a_1}{d}k_1\equiv \frac{m_2-m_1}{d}\pmod {\frac{a_2}{d}}
da1k1≡dm2−m1(modda2)
到这里我们已经消除了
k
2
k_2
k2,继续消除
k
1
k_1
k1即可
对同余式两边同除
a
1
d
\frac{a_1}{d}
da1,得:
k
1
≡
i
n
v
(
a
1
d
,
a
2
d
)
×
m
2
−
m
1
d
(
m
o
d
a
2
d
)
k_1\equiv inv(\frac{a_1}{d},\frac{a_2}{d})\times\frac{m_2-m_1}{d}\pmod{\frac{a_2}{d}}
k1≡inv(da1,da2)×dm2−m1(modda2)
其中
i
n
v
(
a
,
b
)
inv(a,b)
inv(a,b)表示
a
a
a在模
b
b
b意义下的逆元
将
k
1
k_1
k1用①式替换,得:
x
−
m
1
a
1
≡
i
n
v
(
a
1
d
,
a
2
d
)
×
m
2
−
m
1
d
(
m
o
d
a
2
d
)
\frac{x-m_1}{a_1}\equiv inv(\frac{a_1}{d},\frac{a_2}{d})\times\frac{m_2-m_1}{d}\pmod{\frac{a_2}{d}}
a1x−m1≡inv(da1,da2)×dm2−m1(modda2)
等价于:
x
≡
i
n
v
(
a
1
d
,
a
2
d
)
×
m
2
−
m
1
d
×
a
1
+
m
1
(
m
o
d
a
1
a
2
d
)
x\equiv inv(\frac{a_1}{d},\frac{a_2}{d})\times\frac{m_2-m_1}{d}\times a_1+m_1\pmod{\frac{a_1a_2}{d}}
x≡inv(da1,da2)×dm2−m1×a1+m1(modda1a2)
至此,
x
x
x已经变成了完全由已知的
a
1
,
a
2
,
m
1
,
m
2
a_1,a_2,m_1,m_2
a1,a2,m1,m2所表达的同余式了。
形式与
x
≡
m
(
m
o
d
a
)
x\equiv m\pmod{a}
x≡m(moda)相同
那么合并后的
m
=
i
n
v
(
a
1
d
,
a
2
d
)
×
m
2
−
m
1
d
×
a
1
+
m
1
m=inv(\frac{a_1}{d},\frac{a_2}{d})\times\frac{m_2-m_1}{d}\times a_1+m_1
m=inv(da1,da2)×dm2−m1×a1+m1,
a
=
l
c
m
(
a
1
,
a
2
)
a=lcm(a_1,a_2)
a=lcm(a1,a2)、
其中
i
n
v
(
a
1
d
,
a
2
d
)
×
m
2
−
m
1
d
inv(\frac{a_1}{d},\frac{a_2}{d})\times\frac{m_2-m_1}{d}
inv(da1,da2)×dm2−m1相当于求解
a
1
k
1
−
a
2
k
2
=
m
2
−
m
1
a_1k_1-a_2k_2=m_2-m_1
a1k1−a2k2=m2−m1得到的最小非负
k
1
k_1
k1
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int n;
ll exgcd(ll a, ll b, ll &x, ll &y) {
if(!b) {
x = 1, y = 0;
return a;
}
ll d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
int main()
{
scanf("%d", &n);
int flag = 1;
ll a1, m1;
for(int i = 1; i <= n; i++) {
if(i == 1) scanf("%lld%lld", &a1, &m1);
else {
ll a2, m2;
scanf("%lld%lld", &a2, &m2);
ll k1, k2;
ll d = exgcd(a1, a2, k1, k2); //求出两个mod的gcd
//判断是否有解
if((m2 - m1) % d) flag = 0;
else {
k1 *= (m2 - m1) / d; //扩大(m2-m1)/d倍
ll t = a2 / d;//求出模:a2/d
k1 = (k1 % t + t) % t;//求出最小的非负k1
m1 = a1 * k1 + m1;//合并后的m
a1 = abs(a1 / d * a2);//合并后的a
}
}
}
if(flag) printf("%lld\n", (m1 % a1 + a1) % a1);
else puts("-1");
}