中国剩余定理
x %
m
1
m_1
m1 =
a
1
a_1
a1 (1)
x %
m
2
m_2
m2 =
a
2
a_2
a2 (2)
…
x %
m
n
m_n
mn =
a
n
a_n
an (n)
m
1
m_1
m1,
m
2
m_2
m2,…
m
n
m_n
mn两两互质,求解x
定理推导
设
M
i
=
∏
j
=
1
,
j
!
=
i
n
m
j
设M_i = \prod_{j=1,j!=i}^nm_j
设Mi=∏j=1,j!=inmj
∵
对
于
任
意
的
j
!
=
i
,
M
i
%
m
j
=
0
,
M
i
%
m
i
!
=
0
\because对于任意的j!=i,M_i \% m_j = 0,M_i\%m_i!=0
∵对于任意的j!=i,Mi%mj=0,Mi%mi!=0
∴
设
K
i
=
M
i
∗
M
i
−
1
+
a
i
(
M
i
−
1
为
m
i
下
的
逆
元
)
\therefore设K_i=M_i*M_i^{-1}+a_i(M_i^{-1}为m_i下的逆元)
∴设Ki=Mi∗Mi−1+ai(Mi−1为mi下的逆元)
那
么
对
于
任
意
的
j
!
=
i
,
K
i
%
m
j
=
0
,
K
i
%
m
i
=
=
a
i
那么对于任意的j!=i,K_i \% m_j = 0,K_i\%m_i==a_i
那么对于任意的j!=i,Ki%mj=0,Ki%mi==ai
∴
x
=
∑
i
=
0
n
K
i
\therefore x = \sum_{i=0}^n K_i
∴x=∑i=0nKi
扩展中国剩余定理
x %
m
1
m_1
m1 =
a
1
a_1
a1 (1)
x %
m
2
m_2
m2 =
a
2
a_2
a2 (2)
…
x %
m
n
m_n
mn =
a
n
a_n
an (n)
m
1
m_1
m1,
m
2
m_2
m2,…
m
n
m_n
mn两两不一定互质,求解x
推导过程
若n = 1,显然x = k
m
1
m_1
m1 +
a
1
a_1
a1 (k为任意数)
所以我们尝试合并方程即可
将(1)式(2)式拿出
则
k
1
m
1
+
a
1
k_1m_1 + a_1
k1m1+a1 =
k
2
m
2
+
a
2
k_2m_2 + a_2
k2m2+a2
即
k
1
m
1
−
k
2
m
2
=
a
2
−
a
1
k_1m_1 - k_2m_2 = a_2 - a_1
k1m1−k2m2=a2−a1
若
(
a
2
−
a
1
)
(a_2-a_1)
(a2−a1) % gcd(
m
1
,
m
2
m_1,m_2
m1,m2) != 0 ,则x无解
否则利用扩展欧几里得即可计算出
k
1
k_1
k1
ext_gcd(
m
1
,
m
2
,
k
1
,
k
2
m_1,m_2,k_1,k_2
m1,m2,k1,k2),算出该方程等于gcd(
m
1
,
m
2
m_1,m_2
m1,m2)时的解
然后乘以
(
a
2
−
a
1
)
/
g
c
d
(
m
1
,
m
2
)
(a_2 - a_1) / gcd(m_1,m_2)
(a2−a1)/gcd(m1,m2),即可得出合并
(
1
)
式
,
(
2
)
式
的
k
1
,
从
而
算
出
满
足
(
1
)
式
(
2
)
式
的
x
′
。
即
x
′
=
k
1
∗
m
1
+
a
1
,
但
是
问
题
是
这
个
x
′
并
不
一
定
满
足
(
3
)
式
。
所
以
我
们
要
利
用
x
′
写
出
x
的
通
解
,
那
么
x
的
通
解
就
应
该
是
x
′
加
上
l
c
m
(
m
1
,
m
2
)
(1)式,(2)式的k_1,从而算出满足(1)式(2)式的x'。\\即x'=k_1*m_1+a_1,但是问题是这个x'并不一定满足(3)式。\\所以我们要利用x'写出x的通解,那么x的通解就应该是x'加上lcm(m_1,m_2)
(1)式,(2)式的k1,从而算出满足(1)式(2)式的x′。即x′=k1∗m1+a1,但是问题是这个x′并不一定满足(3)式。所以我们要利用x′写出x的通解,那么x的通解就应该是x′加上lcm(m1,m2)
所以x的通解为
x
′
+
k
∗
l
c
m
(
m
1
,
m
2
)
,
这
样
a
1
=
x
′
,
m
1
=
l
c
m
(
m
1
,
m
2
)
,
这
样
第
二
个
式
子
就
被
化
掉
了
x'+k*lcm(m_1,m_2),这样a_1 = x',m_1 = lcm(m1,m2),这样第二个式子就被化掉了
x′+k∗lcm(m1,m2),这样a1=x′,m1=lcm(m1,m2),这样第二个式子就被化掉了
同理合并(3)式,(4)式,…(n)式后x =
k
1
m
1
+
a
1
k_1m_1 + a_1
k1m1+a1
/*
扩展中国剩余定理
求n个同余方程的解
输出最小的正整数解
这个就算同余方程的右边是负数也能做
*/
#include <cstdio>
using namespace std;
typedef long long ll;
int n;
ll m[100005],a[100005];
ll ext_gcd(ll m1,ll m2,ll &k1,ll &k2)
{
ll d = m1;
if( !m2 )
{
k1 = 1;
k2 = 0;
}else
{
d = ext_gcd(m2,m1%m2,k2,k1);
k2 -= (m1/m2) * k1;
}
return d;
}
ll q_mul(ll a,ll b,ll mod)
{
ll res = 0;
ll flag = 1;
if( b < 0 )
{
b = -b;
flag = -1;
}
while( b != 0 )
{
if( b & 1 ) res += a;
a += a;
a %= mod;
b >>= 1;
}
return res * flag;
}
ll ext_CRT()
{
a[1] %= m[1];
//if( a[1] == 0 ) a[1] += m[1]; //若要求大于0,加上这一句
ll k1,k2;
for (int i = 2; i <= n; i++)
{
ll d = ext_gcd(m[1],m[i],k1,k2);
if( (a[i] - a[1]) % d ) //两个式子无法合并,说明无解
{
return -1;
}
ll t = m[i] / d; //这里m[i]一定为正,否则直接取绝对值,因为要最小整数解
k1 %= t;
ll z = (a[i]-a[1])/d;
k1 = q_mul(k1,z,t);
k1 = (k1 % t + t) % t;
a[1] = k1 * m[1] + a[1];
m[1] = m[1] * ( m[i] / d );
a[1] %= m[1];
//if( a[1] == 0 ) a[1] += m[1]; //保证大于0
}
return a[1];
}
int main()
{
scanf("%d",&n);
for (int i = 1; i <= n; i++)
{
scanf("%lld%lld",&m[i],&a[i]); // x % mi = ai
}
printf("%lld\n",ext_CRT());
return 0;
}