#define _(x,y) (x%y+y)%y
Exgcd(扩展欧几里得算法)
为了求解方程 a x + b y = c ax+by=c ax+by=c 的一组解
我们可以先使用扩展欧几里得算法求解方程 a x + b y = gcd ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b)
不妨令 a 2 = b 1 , b 2 = a 1 m o d b 1 a_2=b_1,b_2=a_1 \bmod b_1 a2=b1,b2=a1modb1
对于方程:
{
a
1
x
1
+
b
1
y
1
=
gcd
(
a
1
,
b
1
)
a
2
x
2
+
b
2
y
2
=
gcd
(
a
2
,
b
2
)
\begin{cases} a_1x_1+b_1y_1=\gcd(a_1,b_1) \\ a_2x_2+b_2y_2=\gcd(a_2,b_2) \end{cases}
{a1x1+b1y1=gcd(a1,b1)a2x2+b2y2=gcd(a2,b2)
因为
gcd ( a 1 , b 1 ) = gcd ( b 1 , a 1 m o d b 1 ) = gcd ( a 2 , b 2 ) \gcd(a_1,b_1)=\gcd(b_1,a_1 \bmod b_1)=\gcd(a_2,b_2) gcd(a1,b1)=gcd(b1,a1modb1)=gcd(a2,b2)
联立可得:
a 1 x 1 + b 1 y 1 = b 1 x 2 + ( a 1 m o d b 1 ) ⋅ y 2 a_1x_1+b_1y_1=b_1x_2+(a_1\bmod b_1)\cdot y_2 a1x1+b1y1=b1x2+(a1modb1)⋅y2
a
1
x
1
+
b
1
y
1
=
b
1
x
2
+
(
a
1
−
⌊
a
1
b
1
⌋
⋅
b
1
)
⋅
y
2
a_1x_1+b_1y_1=b_1x_2+(a_1-\lfloor\dfrac{a_1}{b_1}\rfloor\cdot b_1)\cdot y_2
a1x1+b1y1=b1x2+(a1−⌊b1a1⌋⋅b1)⋅y2
a
1
x
1
+
b
1
y
1
=
b
1
x
2
+
a
1
y
2
−
⌊
a
1
b
1
⌋
⋅
b
1
y
2
a_1x_1+b_1y_1=b_1x_2+a_1y_2-\lfloor\dfrac{a_1}{b_1}\rfloor\cdot b_1y_2
a1x1+b1y1=b1x2+a1y2−⌊b1a1⌋⋅b1y2
a
1
x
1
+
b
1
y
1
=
a
1
y
2
+
b
1
⋅
(
x
2
−
⌊
a
1
b
1
⌋
⋅
y
2
)
a_1x_1+b_1y_1=a_1y_2+b_1\cdot(x_2-\lfloor\dfrac{a_1}{b_1}\rfloor\cdot y_2)
a1x1+b1y1=a1y2+b1⋅(x2−⌊b1a1⌋⋅y2)
显然 x 1 = y 2 , y 1 = x 2 − ⌊ a 1 b 1 ⌋ ⋅ y 2 x_1=y_2,y_1=x_2-\lfloor\dfrac{a_1}{b_1}\rfloor\cdot y_2 x1=y2,y1=x2−⌊b1a1⌋⋅y2 时原方程成立
因此,只要求出 x 2 x_2 x2 和 y 2 y_2 y2 ,则可求出 x 1 x_1 x1 和 y 1 y_1 y1
而在函数中, x 1 x_1 x1 的返回值为 y 2 y_2 y2 , y 1 y_1 y1 的返回值为 x 2 x_2 x2
为了调整当前返回值, y 1 = x 2 − ⌊ a 1 b 1 ⌋ ⋅ y 2 = y 1 − ⌊ a 1 b 1 ⌋ ⋅ x 1 y_1=x_2-\lfloor\dfrac{a_1}{b_1}\rfloor\cdot y_2=y_1-\lfloor\dfrac{a_1}{b_1}\rfloor\cdot x_1 y1=x2−⌊b1a1⌋⋅y2=y1−⌊b1a1⌋⋅x1
(联系返回值来理解,当然你也可以让
x
1
x_1
x1 的返回值为
x
2
x_2
x2 ,
y
1
y_1
y1 的返回值为
y
2
y_2
y2 但那个亚子就没压行好看了
显然,当
b
=
0
b=0
b=0 时,原方程转换为
a
x
=
a
ax=a
ax=a ,一定存在一组解
{
x
=
1
y
=
0
\begin{cases} x=1 \\ y=0 \end{cases}
{x=1y=0
代码如下:
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(!b) return x=1,y=0,a;
LL Q=exgcd(b,a%b,y,x);
return y-=a/b*x,Q;
}
Excrt (扩展中国剩余定理)
为了求解同余方程组的一个解
{
x
≡
a
1
(
m
o
d
m
1
)
x
≡
a
2
(
m
o
d
m
2
)
.
.
.
x
≡
a
n
(
m
o
d
m
n
)
\begin{cases} x\equiv a_1\pmod{m_1}\\ x\equiv a_2\pmod{m_2}\\ ...\\ x\equiv a_n\pmod{m_n} \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧x≡a1(modm1)x≡a2(modm2)...x≡an(modmn)
我们先将前 i − 1 i-1 i−1 个同余方程合并成一个船新的同余方程 x ≡ A ( m o d M ) x\equiv A\pmod{M} x≡A(modM),且这个同余方程满足前 i − 1 i-1 i−1 个同余方程的约束
现在我们来考虑怎么合并第 i i i 个同余方程
对于同余方程 x ≡ A ( m o d M ) x\equiv A\pmod{M} x≡A(modM) , x x x 的通解为 x = A + M ⋅ k x=A+M \cdot k x=A+M⋅k
将其代入第 i i i 个同余方程得 $A+M\cdot k\equiv a_i \pmod{m_i} $
化简得 x ⋅ M + y ⋅ m i = A − a i x \cdot M+y \cdot m_i =A-a_i x⋅M+y⋅mi=A−ai ,其中 x , y x,y x,y 为未知数
使用扩展欧几里得算法可以解得方程 x ⋅ M + y ⋅ m i = gcd ( M , m i ) x\cdot M+y \cdot m_i=\gcd(M,m_i) x⋅M+y⋅mi=gcd(M,mi) 的一组特解
记 x 0 = gcd ( M , m i ) x_0=\gcd(M,m_i) x0=gcd(M,mi) , C = A − a i C=A-a_i C=A−ai (注意调整 C C C 的值 [ 0 , m i ) [0,m_i) [0,mi)
若 x 0 ∣ C x_0|C x0∣C 则原方程有解,此时应将 x x x 调整为原方程的解,即 x = x ⋅ C x 0 x=x \cdot \dfrac{C}{x_0} x=x⋅x0C
此时 x x x 满足前 i i i 组同余方程
因为 x ⋅ M ≡ A − a i ( m o d m i ) x\cdot M \equiv A-a_i \pmod{m_i} x⋅M≡A−ai(modmi) ,所以 A − x ⋅ M ≡ a i ( m o d m i ) A -x\cdot M\equiv a_i \pmod{m_i} A−x⋅M≡ai(modmi)
令 A ′ = A − x ⋅ M , M ′ = M ⋅ m i gcd ( M , m i ) A^{'} =A-x \cdot M,M^{'}=\dfrac{M\cdot m_i}{\gcd(M,m_i)} A′=A−x⋅M,M′=gcd(M,mi)M⋅mi
因为 A ′ ≡ A ( m o d M ) A^{'} \equiv A \pmod{M} A′≡A(modM) 且 A ′ ≡ a i ( m o d m i ) A^{'} \equiv a_i\pmod{m_i} A′≡ai(modmi)
则两个同余方程可合并为 x ≡ A ′ ( m o d M ′ ) x \equiv A^{'}\pmod{M^{'}} x≡A′(modM′)
代码如下:
LL excrt()
{
LL M=m[1],A=a[1];
for(int i=2;i<=n;i++)
{
LL x,y,x0=exgcd(M,m[i],x,y);
LL C=_(A-a[i],m[i]);
if(C%x0) return -1;
x=ksc(x,C/x0,m[i]);
x%=m[i];A-=x*M;M*=m[i]/x0;A%=M;
}
if(A%M==0) return M;
return _(A,M);
}