中国剩余定理:
中国剩余定理(孙子定理)是用于解决一次同余方程组的一种方法。
定理的思路是将两个同余方程合为一个再下一个方程合并,最后得到答案。
那么先来看看对于两个方程的合并:
x = a1(mod n1)
x = a2(mod n2)
将方程都转换为乘积与和的形式:
x = n1 * T1+a1
x = n2 * T2+a2
将上述两式合并整理得:
n1T1=(a2-a1)+n2T2
设gcd(n1,n2) = d,c = a2 - a1,则合并的同余方程可变形为
(n1/d)*T1 = (c/d)(mod n2/d)
T1 =(c/d)*(n1/d)^-1(mod n2/d)
不妨设S = (c/d)(n1/d)^-1,则T1=t(n2/d) + S,那么
x = n1[t*(n2/d)+S]+a1 = (n1n2/d) t + n1S+a1,即x = n1S+a1(mod n1*n2/d)
那么在带入求解时新的a3 = n1S + a1,n3 = n1n2/d,最终,其中最小的x就是最后剩余的方程的a(mod n)
#include"iostream"
using namespace std;
typedef long long LL;
LL r[1001],m[1001],N;
LL gcd(LL a,LL b){
return b?gcd(b,a%b):a;
}
LL ex_gcd(LL a,LL b,LL &x,LL &y){
if(b == 0){
x = 1;
y = 0;
return a;
}
LL d = ex_gcd(b,a%b,x,y);
LL t = x;
x = y;
y = t -(a/b)*y;
return d;
}
LL Inv(LL a,LL b){
LL d = gcd(a,b);
if(d!=1)return -1;
LL x,y;
ex_gcd(a,b,x,y);
return (x%b+b)%b;
}
bool megre(LL r1,LL m1,LL r2,LL m2,LL &r3,LL &m3){
LL d = gcd(m1,m2);
LL r = r2-r1;
if(r%d)return 0;
r = (r%m2+m2)%m2;
m1/=d;m2/=d;r/=d;
r*=Inv(m1,m2);
r%=m2;r*=m1*d;r+=r1;
m3 = m1*m2*d;
r3 = (r%m3+m3)%m3;
return 1;
}
LL CRT(){
LL A1 = r[1],B1 = m[1];
for(int i = 2;i <= N;i++){
LL A2 = r[i],B2 = m[i];
LL A3,B3;
if(!megre(A1,B1,A2,B2,A3,B3))return -1;
A1 = A3;
B1 = B3;
}
return (A1%B1+B1)%B1;
}
int main(){
cin >> N;
for(int i = 1;i <= N;i++)
cin >> m[i];
for(int i = 1;i<= N;i++)
cin >> r[i];
cout <<CRT();
return 0;
}