①. 题目
②. 思路
- 中国剩余定理要求a1,a2,…,an两两互质
③. 学习点
中国剩余定理
④. 代码实现
import java.util.Scanner;
public class Main {
static long k1,k2;
//扩展欧几里得模板
static long gcd(long a,long b) {
if(b==0) {
k1=1;k2=0;
return a;
}
long d=gcd(b,a%b);
long tmp=k1;
k1=k2;
k2=tmp-a/b*k1;
return d;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n=sc.nextInt();
long a1=sc.nextLong();
long m1=sc.nextLong();
boolean flag=true;
while(n-->1) {
long a2=sc.nextLong();
long m2=sc.nextLong();
//扩展欧几里得求最大公约数
long d=gcd(a1,a2);
long t=a2/d; //k1的取值范围
//k1*a1-k2*a2=m2-m1
//根据扩展欧几里得k1=k1∗(m2−m1)/gcd(a1,a2)
k1=k1*(m2-m1)/d;
if((m2-m1)%d!=0) {
//无解
flag=false;
break;
}
k1=(k1%t+t)%t;//取k1+k( a2 / d )最小值 防止出现负数
//此时公式变形为x=( a1*k1+m1 )+( k*[a1,a2] ),k取任何整数,所以可以替换k1、k2、、
m1=a1*k1+m1 ;
//[]代表最小公倍数= 两个数乘积/两个数最大公约数
a1=a1/d*a2;
}
if(flag) {
//因为每次都是两个式子合并,而且每个x=k*a+m,而维护到最后一次的时候公式里的 m1=a1*k1+m1,a1=a1/d*a2
//所以到最后会合并成一个式子:x= m1(%a1) = k*a1+m1 。这时候让%a1移到左边
//变为m1 % a1 = x,此时结果就是取m1 % a1最小正整数
System.out.println((m1%a1+a1)%a1);//(m1 % a1的最小正整数)
}else {
System.out.println(-1);
}
}
}