形式:
{
x
≡
a
1
(
m
o
d
m
1
)
x
≡
a
2
(
m
o
d
m
2
)
.
.
.
x
≡
a
n
(
m
o
d
m
n
)
\left\{\begin{array}{l} x \equiv a_1(mod\ m_1)\\ x \equiv a_2(mod\ m_2)\\ ...\\ x \equiv a_n(mod\ m_n) \end{array}\right.
⎩⎪⎪⎨⎪⎪⎧x≡a1(mod m1)x≡a2(mod m2)...x≡an(mod mn)
其中
(
m
i
,
m
j
)
=
1
,
(
i
≠
j
)
(m_i,m_j)=1,(i\neq j)
(mi,mj)=1,(i=j),求出最小的
x
x
x
公式:
设
M
=
∏
i
=
1
n
m
i
M=\overset{n}{\underset{i=1}{\prod}} m_i
M=i=1∏nmi,
M
i
=
M
m
i
M_i=\frac{M}{m_i}
Mi=miM,因为
(
M
i
,
m
i
)
=
1
(M_i,m_i)=1
(Mi,mi)=1,
故存在 M i M_i Mi关于 m i m_i mi的逆元 M i − 1 M_i^{-1} Mi−1,那么 x = ( ∑ i = 1 n a i ⋅ M i ⋅ M i − 1 ) m o d M x=(\overset{n}{\underset{i=1}{\sum}}a_i \cdot M_i \cdot M_i^{-1}) \ mod\ M x=(i=1∑nai⋅Mi⋅Mi−1) mod M
由于 m i m_i mi不一定为质数,所有这里用 e x g c d exgcd exgcd求解 M i − 1 M_i^{-1} Mi−1
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 15;
ll A[N], m[N];
int n;
void exgcd(ll a, ll b, ll &x, ll &y) {
if(!b) {
x = 1, y = 0;
return ;
}
exgcd(b, a % b, y, x);
y -= a / b * x;
}
int main()
{
scanf("%d", &n);
ll MM = 1;
for(int i = 1; i <= n; i++)
scanf("%lld%lld", &m[i], &A[i]), MM *= m[i];
ll res = 0;
for(int i = 1; i <= n; i++) {
ll Mi = MM / m[i];
ll x, y;
exgcd(Mi, m[i], x, y);
res = ((res + A[i] * Mi * x) % MM + MM) % MM;
}
printf("%lld\n", res);
return 0;
}
完整推导过程推荐:传送门