中国剩余定理

中国剩余定理:
中国剩余定理(孙子定理)是用于解决一次同余方程组的一种方法。
定理的思路是将两个同余方程合为一个再下一个方程合并,最后得到答案。

那么先来看看对于两个方程的合并:

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 n1n2/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;
}
原文地址:https://www.cnblogs.com/PHKCOOL/p/10946602.html