>Link
luogu P4777
>Description
求解一元线性同余方程组
{
x
≡
b
1
(
m
o
d
a
1
)
.
.
.
.
.
.
x
≡
b
n
(
m
o
d
a
n
)
\left\{\begin{matrix}x\equiv b_1(mod a_1) \\ ...... \\ x\equiv b_n(mod a_n) \end{matrix}\right.
⎩⎨⎧x≡b1(moda1)......x≡bn(modan)
不保证
a
a
a两两互质
>解题思路
由于模数不保证两两互质,所以我们就不能用中国剩余定理的方法exgcd了
要用扩展中国剩余定理
参考自:建议看看这个巨爷的笔记QAQ,这里做个总结
我们先考虑两个式子
{
x
≡
b
1
(
m
o
d
a
1
)
x
≡
b
2
(
m
o
d
a
2
)
\left\{\begin{matrix}x\equiv b_1(mod a_1) \\ x\equiv b_2(mod a_2) \end{matrix}\right.
{x≡b1(moda1)x≡b2(moda2)
可以转换成
{
x
=
b
1
+
a
1
∗
k
1
x
=
b
2
+
a
2
∗
k
2
\left\{\begin{matrix}x= b_1+a_1*k_1 \\ x=b_2+a_2 * k_2 \end{matrix}\right.
{x=b1+a1∗k1x=b2+a2∗k2
联立得
b
1
+
a
1
∗
k
1
=
b
2
+
a
2
∗
k
2
b_1+a_1*k_1=b_2+a_2 * k_2
b1+a1∗k1=b2+a2∗k2
移项得
a
1
∗
k
1
−
a
2
∗
k
2
=
b
2
−
b
1
a_1*k_1-a_2 * k_2=b_2-b_1
a1∗k1−a2∗k2=b2−b1
这个式子就可以用exgcd来解决了,但是得满足
g
c
d
(
a
1
,
a
2
)
∣
b
2
−
b
1
gcd(a_1,a_2)|b_2-b_1
gcd(a1,a2)∣b2−b1这个前提(回顾下exgcd:
a
1
∗
k
1
−
a
2
∗
k
2
=
g
c
d
(
a
1
,
a
2
)
a_1*k_1-a_2 * k_2=gcd(a_1,a_2)
a1∗k1−a2∗k2=gcd(a1,a2)),最后求出来两边再乘上
(
b
2
−
b
1
)
/
g
c
d
(
a
1
,
a
2
)
(b_2-b_1)/gcd(a_1,a_2)
(b2−b1)/gcd(a1,a2)就行了
我们设用exgcd求出来的其中两个解为
K
1
K_1
K1和
K
2
K_2
K2,即
a
1
∗
K
1
−
a
2
∗
K
2
=
g
c
d
(
a
1
,
a
2
)
a_1*K_1-a_2 * K_2=gcd(a_1,a_2)
a1∗K1−a2∗K2=gcd(a1,a2)
按照前面说的,两边乘上
(
b
2
−
b
1
)
g
c
d
(
a
1
,
a
2
)
\frac{(b_2-b_1)}{gcd(a_1,a_2)}
gcd(a1,a2)(b2−b1),得到
k
1
=
K
1
∗
(
b
2
−
b
1
)
g
c
d
(
a
1
,
a
2
)
k_1=K_1*\frac{(b_2-b_1)}{gcd(a_1,a_2)}
k1=K1∗gcd(a1,a2)(b2−b1),
k
2
=
K
2
∗
(
b
2
−
b
1
)
g
c
d
(
a
1
,
a
2
)
k_2=K_2*\frac{(b_2-b_1)}{gcd(a_1,a_2)}
k2=K2∗gcd(a1,a2)(b2−b1)
现在我们就可以求出一个
x
x
x了
可是显然不只有一个
x
x
x
设求出来的两个解为
x
0
x_0
x0和
x
1
x_1
x1,满足
x
0
<
x
1
x_0<x_1
x0<x1
两个解都满足同余方程,所以
{
x
0
≡
b
1
(
m
o
d
a
1
)
x
1
≡
b
1
(
m
o
d
a
1
)
\left\{\begin{matrix}x_0\equiv b_1(mod a_1) \\ x_1\equiv b_1(mod a_1) \end{matrix}\right.
{x0≡b1(moda1)x1≡b1(moda1)
{
x
0
≡
b
2
(
m
o
d
a
2
)
x
1
≡
b
2
(
m
o
d
a
2
)
\left\{\begin{matrix}x_0\equiv b_2(mod a_2) \\ x_1\equiv b_2(mod a_2) \end{matrix}\right.
{x0≡b2(moda2)x1≡b2(moda2)
设存在
s
1
s_1
s1和
s
2
s_2
s2,使得
x
1
=
x
0
+
a
1
∗
s
1
x_1= x_0+a_1*s_1
x1=x0+a1∗s1,
x
1
=
x
0
+
a
2
∗
s
2
x_1= x_0+a_2*s_2
x1=x0+a2∗s2
移项得
x
1
−
x
0
=
a
1
∗
s
1
x_1- x_0=a_1*s_1
x1−x0=a1∗s1,
x
1
−
x
0
=
a
2
∗
s
2
x_1- x_0=a_2*s_2
x1−x0=a2∗s2,所以
a
1
∗
s
1
=
a
2
∗
s
2
a_1*s_1=a_2*s_2
a1∗s1=a2∗s2
设
d
1
=
a
1
g
c
d
(
a
1
,
a
2
)
d_1=\frac{a_1}{gcd(a_1,a_2)}
d1=gcd(a1,a2)a1,
d
2
=
a
2
g
c
d
(
a
1
,
a
2
)
d_2=\frac{a_2}{gcd(a_1,a_2)}
d2=gcd(a1,a2)a2(我们知道
g
c
d
(
d
1
,
d
2
)
=
1
gcd(d_1,d_2)=1
gcd(d1,d2)=1),得
d
1
∗
g
c
d
(
a
1
,
a
2
)
∗
s
1
=
d
2
∗
g
c
d
(
a
1
,
a
2
)
∗
s
2
d_1*gcd(a_1,a_2)*s_1=d_2*gcd(a_1,a_2)*s_2
d1∗gcd(a1,a2)∗s1=d2∗gcd(a1,a2)∗s2,即
d
1
∗
s
1
=
d
2
∗
s
2
d_1*s_1=d_2*s_2
d1∗s1=d2∗s2
所以我们得到
d
1
∣
s
2
d_1|s_2
d1∣s2,
d
1
∗
d
2
∣
s
2
∗
d
2
d_1 * d_2|s_2 * d_2
d1∗d2∣s2∗d2
d
1
∗
d
2
∗
g
c
d
(
a
1
,
a
2
)
∣
s
2
∗
d
2
∗
g
c
d
(
a
1
,
a
2
)
d_1 * d_2 *gcd(a_1,a_2)|s_2 * d_2*gcd(a_1,a_2)
d1∗d2∗gcd(a1,a2)∣s2∗d2∗gcd(a1,a2)
l
c
m
(
a
1
,
a
2
)
∣
x
1
−
x
0
lcm(a_1,a_2)|x_1- x_0
lcm(a1,a2)∣x1−x0
所以
x
1
−
x
0
x_1-x_0
x1−x0一定是
l
c
m
(
a
1
,
a
2
)
lcm(a_1,a_2)
lcm(a1,a2)的倍数!!!求出一个
x
x
x,其它加上任意倍
l
c
m
(
a
1
,
a
2
)
lcm(a_1,a_2)
lcm(a1,a2)就行了
so
M
M
M表示当前所有
a
a
a的
l
c
m
lcm
lcm,
X
X
X表示当前解
枚举到当前数,解表示为
X
+
t
∗
M
X+t*M
X+t∗M
满足
X
+
t
∗
M
≡
b
i
(
m
o
d
a
i
)
X+t*M\equiv b_i(mod a_i)
X+t∗M≡bi(modai),移项得
t
∗
M
≡
b
i
−
X
(
m
o
d
a
i
)
t*M\equiv b_i-X(mod a_i)
t∗M≡bi−X(modai)
>代码
//还是不是很懂 需要再看一下QAQ
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
#define LL long long
using namespace std;
int n;
LL a[N], b[N], M, ans;
LL mul (LL aa, LL bb, LL Mod)
{
LL ret = 0;
aa %= Mod;
for (; bb; bb >>= 1, aa = (aa + aa) % Mod)
if (bb & 1) ret = (ret + aa) % Mod;
return ret;
}
LL ex_gcd (LL aa, LL bb, LL &x, LL &y)
{
if (!bb) {x = 1, y = 0; return aa;}
LL X = x, Y = y;
LL ret = ex_gcd (bb, aa % bb, X, Y);
x = Y;
y = X - (aa / bb) * Y;
return ret;
}
int main()
{
scanf ("%d", &n);
for (int i = 1; i <= n; i++)
scanf ("%lld%lld", &a[i], &b[i]);
M = a[1], ans = b[1];
for (int i = 2; i <= n; i++)
{
LL x = 0, y = 0;
LL g = ex_gcd (M, a[i], x, y);
//if ((b[i] - ans) % g != 0) nosolution~
/*x = x * ((b[i] - ans) / g);
LL t = a[i] / g;
x = (x % t + t) % t;*/
LL t = (b[i] - ans % a[i] + a[i]) % a[i];
x = mul (x, t / g, a[i] / g);
ans = ans + x * M;
M = M * (a[i] / g);
ans = (ans % M + M) % M;
}
ans = (ans % M + M) % M;
printf ("%lld", ans);
return 0;
}