求解线性同余方程组
线性同余方程组就是形如这样的方程组:
{
a
1
x
≡
b
1
(
m
o
d
m
1
)
a
2
x
≡
b
2
(
m
o
d
m
2
)
⋮
a
n
x
≡
b
n
(
m
o
d
m
n
)
\begin{cases} a_1x\equiv b_1\ (mod\ m_1)\\ a_2x\equiv b_2\ (mod\ m_2)\\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \vdots \\ a_nx\equiv b_n\ (mod\ m_n)\\ \end{cases}
⎩ ⎪ ⎪ ⎪ ⎪ ⎨ ⎪ ⎪ ⎪ ⎪ ⎧ a 1 x ≡ b 1 ( m o d m 1 ) a 2 x ≡ b 2 ( m o d m 2 ) ⋮ a n x ≡ b n ( m o d m n )
与扩展中国剩余定理的证明类似,首先找出一个形如这样的方程:
x
≡
b
0
(
m
o
d
m
0
)
x\equiv b_0\ (mod\ m_0)
x ≡ b 0 ( m o d m 0 )
可以化为:
x
=
b
0
+
m
0
k
0
x=b_0+m_0k_0
x = b 0 + m 0 k 0
第一步可以假定
b
1
=
0
,
m
1
=
1
b_1=0,m_1=1
b 1 = 0 , m 1 = 1 ,代表解是所有的正整数。
之后与方程组的第一个方程联立:
{
x
≡
b
0
(
m
o
d
m
0
)
a
1
x
≡
b
1
(
m
o
d
m
1
)
\begin{cases} x\equiv b_0\ (mod\ m_0)\\ a_1x\equiv b_1\ (mod\ m_1) \end{cases}
{ x ≡ b 0 ( m o d m 0 ) a 1 x ≡ b 1 ( m o d m 1 )
把一式带入二式得:$
a
1
(
b
0
+
m
0
k
0
)
≡
b
1
(
m
o
d
m
1
)
a_1(b_0+m_0k_0)\equiv b_1\ (mod\ m_1)
a 1 ( b 0 + m 0 k 0 ) ≡ b 1 ( m o d m 1 )
a
1
b
0
+
a
1
m
0
k
0
=
b
1
+
m
1
k
1
a_1b_0+a_1m_0k_0=b_1+m_1k_1
a 1 b 0 + a 1 m 0 k 0 = b 1 + m 1 k 1
a
1
m
0
k
0
=
b
1
−
a
1
b
0
+
m
1
k
1
a_1m_0k_0=b_1-a_1b_0+m_1k_1
a 1 m 0 k 0 = b 1 − a 1 b 0 + m 1 k 1
此时令
(
a
,
b
)
(a, b)
( a , b ) 表示
g
c
d
(
a
,
b
)
gcd(a,b)
g c d ( a , b ) ,则有:
a
1
m
1
(
a
1
m
0
,
m
1
)
k
0
=
b
1
−
a
1
b
0
(
a
1
m
0
,
m
1
)
+
m
1
(
a
1
m
0
,
m
1
)
k
1
\frac{a_1m_1}{(a_1m_0,m_1)}k_0=\frac{b_1-a_1b_0}{(a_1m_0,m_1)}+\frac{m_1}{(a_1m_0,m_1)}k_1
( a 1 m 0 , m 1 ) a 1 m 1 k 0 = ( a 1 m 0 , m 1 ) b 1 − a 1 b 0 + ( a 1 m 0 , m 1 ) m 1 k 1
(此时
(
a
1
m
0
,
m
1
)
(a_1m_0,m_1)
( a 1 m 0 , m 1 ) 一定要能够整除
b
1
−
a
1
b
0
b_1-a_1b_0
b 1 − a 1 b 0 ,否则方程无解)
所以有:
a
1
m
0
(
a
1
m
0
,
m
1
)
k
0
≡
b
1
−
a
1
b
0
(
a
1
m
0
,
m
1
)
(
m
o
d
m
1
(
a
1
m
0
,
m
1
)
)
\frac{a_1m_0}{(a_1m_0,m_1)}k_0\equiv \frac{b_1-a_1b_0}{(a_1m_0,m_1)}\ (mod\ \frac{m_1}{(a_1m_0,m_1)})
( a 1 m 0 , m 1 ) a 1 m 0 k 0 ≡ ( a 1 m 0 , m 1 ) b 1 − a 1 b 0 ( m o d ( a 1 m 0 , m 1 ) m 1 )
k
0
≡
b
1
−
a
1
b
0
(
a
1
m
0
,
m
1
)
i
n
v
(
a
1
m
0
(
a
1
m
0
,
m
1
)
,
m
1
(
a
1
m
0
,
m
1
)
)
(
m
o
d
m
1
(
a
1
m
0
,
m
1
)
)
k_0\equiv \frac{b_1-a_1b_0}{(a_1m_0,m_1)}inv(\frac{a_1m_0}{(a_1m_0,m_1)},\frac{m_1}{(a_1m_0,m_1)})\ (mod\ \frac{m_1}{(a_1m_0,m_1)})
k 0 ≡ ( a 1 m 0 , m 1 ) b 1 − a 1 b 0 i n v ( ( a 1 m 0 , m 1 ) a 1 m 0 , ( a 1 m 0 , m 1 ) m 1 ) ( m o d ( a 1 m 0 , m 1 ) m 1 )
k
0
=
b
1
−
a
1
b
0
(
a
1
m
0
,
m
1
)
i
n
v
(
a
1
m
0
(
a
1
m
0
,
m
1
)
,
m
1
(
a
1
m
0
,
m
1
)
)
+
y
m
1
(
a
1
m
0
,
m
1
)
k_0=\frac{b_1-a_1b_0}{(a_1m_0,m_1)}inv(\frac{a_1m_0}{(a_1m_0,m_1)},\frac{m_1}{(a_1m_0,m_1)})+y\frac{m_1}{(a_1m_0,m_1)}
k 0 = ( a 1 m 0 , m 1 ) b 1 − a 1 b 0 i n v ( ( a 1 m 0 , m 1 ) a 1 m 0 , ( a 1 m 0 , m 1 ) m 1 ) + y ( a 1 m 0 , m 1 ) m 1
代入高亮的上式:
x
=
b
1
−
a
1
b
0
(
a
1
m
0
,
m
1
)
i
n
v
(
a
1
m
0
(
a
1
m
0
,
m
1
)
,
m
1
(
a
1
m
0
,
m
1
)
)
m
0
+
y
m
0
m
1
(
a
1
m
0
,
m
1
)
+
b
0
x=\frac{b_1-a_1b_0}{(a_1m_0,m_1)}inv(\frac{a_1m_0}{(a_1m_0,m_1)},\frac{m_1}{(a_1m_0,m_1)})m_0+y\frac{m_0m_1}{(a_1m_0,m_1)}+b_0
x = ( a 1 m 0 , m 1 ) b 1 − a 1 b 0 i n v ( ( a 1 m 0 , m 1 ) a 1 m 0 , ( a 1 m 0 , m 1 ) m 1 ) m 0 + y ( a 1 m 0 , m 1 ) m 0 m 1 + b 0
x
≡
b
1
−
a
1
b
0
(
a
1
m
0
,
m
1
)
i
n
v
(
a
1
m
0
(
a
1
m
0
,
m
1
)
,
m
1
(
a
1
m
0
,
m
1
)
)
m
0
+
b
0
(
m
o
d
m
0
m
1
(
a
1
m
0
,
m
1
)
)
x\equiv \frac{b_1-a_1b_0}{(a_1m_0,m_1)}inv(\frac{a_1m_0}{(a_1m_0,m_1)},\frac{m_1}{(a_1m_0,m_1)})m_0+b_0\ (mod\ \frac{m_0m_1}{(a_1m_0,m_1)})
x ≡ ( a 1 m 0 , m 1 ) b 1 − a 1 b 0 i n v ( ( a 1 m 0 , m 1 ) a 1 m 0 , ( a 1 m 0 , m 1 ) m 1 ) m 0 + b 0 ( m o d ( a 1 m 0 , m 1 ) m 0 m 1 )
此时可以将方程看作:
x
≡
b
(
m
o
d
m
)
x\equiv b\ (mod\ m)
x ≡ b ( m o d m )
其中
b
=
(
b
1
−
a
1
b
0
(
a
1
m
0
,
m
1
)
i
n
v
(
a
1
m
0
(
a
1
m
0
,
m
1
)
,
m
1
(
a
1
m
0
,
m
1
)
)
)
%
m
1
(
a
1
m
0
,
m
1
)
m
0
+
b
0
b=(\frac{b_1-a_1b_0}{(a_1m_0,m_1)}inv(\frac{a_1m_0}{(a_1m_0,m_1)},\frac{m_1}{(a_1m_0,m_1)}))\%\frac{m_1}{(a_1m_0,m_1)}m_0+b_0
b = ( ( a 1 m 0 , m 1 ) b 1 − a 1 b 0 i n v ( ( a 1 m 0 , m 1 ) a 1 m 0 , ( a 1 m 0 , m 1 ) m 1 ) ) % ( a 1 m 0 , m 1 ) m 1 m 0 + b 0
m
=
m
0
m
1
(
a
1
m
0
,
m
1
)
m=\frac{m_0m_1}{(a_1m_0,m_1)}
m = ( a 1 m 0 , m 1 ) m 0 m 1
到这里,式子里所有的值我们都知道了,并且得到了一个新的同余式。再把新的和其他的联立,依此循环,最终求出通解。
代码
pair< int , int > linear_congruence ( const vector< int > & A, const vector< int > & B, const vector< int > & M) {
int b = 0 , m = 1 ;
for ( int i = 0 ; i < A. size ( ) ; i++ ) {
int a = A[ i] * m, b = B[ i] - A[ i] * b, d = gcd ( M[ i] , a) ;
if ( b% d != 0 ) return make_pair ( 0 , - 1 ) ;
int t = b / d * mod_inverse ( a / d, M[ i] / d) % ( M[ i] / d) ;
b = b + m * t;
m * = M[ i] / d;
}
return make_pair ( x % m, m) ;
}