分析:
前置知识:
e
x
g
c
d
exgcd
exgcd,
c
r
t
crt
crt
e
x
g
c
d
exgcd
exgcd用来解同余方程
c
r
t
crt
crt用来解同余方程组 其中
p
i
p_i
pi互质
e
x
c
r
t
excrt
excrt也可以解同余方程组 但
p
i
p_i
pi可以不互质
先不用管合并所有方程组 考虑合并两个
{
x
≡
A
(
m
o
d
P
)
x
≡
a
i
(
m
o
d
p
i
)
\begin{cases} x ≡A~(mod~P) \\ x≡a_i~(mod~p_i) \end{cases}
{x≡A (mod P)x≡ai (mod pi)
化成正常形式:
{
x
=
A
+
P
k
1
x
=
a
i
+
p
i
k
2
\begin{cases} x=A+Pk_1\\ x=a_i+p_ik_2 \end{cases}
{x=A+Pk1x=ai+pik2
上下相减 得
P
k
1
−
p
i
k
2
=
a
i
−
A
Pk_1-p_ik_2=a_i-A
Pk1−pik2=ai−A
用
e
x
g
c
d
exgcd
exgcd可求出
k
1
=
p
i
l
+
b
k_1=p_il+b
k1=pil+b
(
l
(l
(l为任意整数
)
)
)
代入回去就可以得出
x
=
A
+
P
p
i
l
+
P
b
x=A+Pp_il+Pb
x=A+Ppil+Pb
然后这是
p
i
p_i
pi和
P
P
P互质的时候 也就是普通
c
r
t
crt
crt
再考虑
p
i
p_i
pi和
P
P
P不互质 先除去
g
c
d
(
p
i
,
P
)
gcd(p_i,P)
gcd(pi,P)
即
P
g
c
d
(
p
i
,
P
)
k
1
−
p
i
g
c
d
(
p
i
,
P
)
k
2
=
a
i
−
A
g
c
d
(
p
i
,
P
)
\frac{P}{gcd(p_i,P)}k_1~-~\frac{p_i}{gcd(p_i,P)}k_2=\frac{a_i-A}{gcd(p_i,P)}
gcd(pi,P)Pk1 − gcd(pi,P)pik2=gcd(pi,P)ai−A
同理
e
x
g
c
d
exgcd
exgcd得出
k
1
=
p
i
g
c
d
(
p
i
,
P
)
l
+
b
k_1=\frac{p_i}{gcd(p_i,P)}l+b
k1=gcd(pi,P)pil+b
然后同样代入回去
x
=
A
+
l
c
m
(
p
i
,
P
)
l
+
P
b
x=A+lcm(p_i,P)l+Pb
x=A+lcm(pi,P)l+Pb
复杂度
O
(
n
l
o
g
n
)
O(n~log~n)
O(n log n)
如果防溢出 还要用龟速乘 求最小非负数解每次要处理下
CODE:
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e6+5;
int n;
ll a[N],p[N],x,y;
ll mul(ll a,ll k,ll Mod)
{
ll res=0;
while(k)
{
if(k&1) (res+=a)%=Mod;
k>>=1;
(a+=a)%=Mod;
}
return res;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
ll res=exgcd(b,a%b,x,y);
ll k=x;
x=y;
y=k-a/b*y;
return res;
}
ll excrt()
{
ll Mod=p[1],ans=a[1];
for(int i=2;i<=n;i++)
{
ll k=((a[i]-ans)%p[i]+p[i])%p[i];
ll gcd=exgcd(Mod,p[i],x,y);
ll qwq=p[i]/gcd;
x=mul(x,k/gcd,qwq);
ans+=x*Mod;
Mod*=qwq;
ans=(ans%Mod+Mod)%Mod;
}
return ans;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld%lld",&p[i],&a[i]);
printf("%lld",excrt());
return 0;
}