令 $d=gcd(a_1,a_2)$,如果 $(b_2-b_1)\%d \ne 0$,那么无解。
否则对于方程两边同时除以 $d$,
$k_1\frac{a_1}{d}-k_2\frac{a_2}{d}=\frac{b_2-b_1}{d}$,
$k_1\frac{a_1}{d}=\frac{b_2-b_1}{d}+k_2\frac{a_2}{d}$,
可以看作 $k_1\frac{a_1}{d}\%\frac{a_2}{d}=\frac{b_2-b_1}{d}$,
令 $inv=\frac{a_1}{d} \% \frac{a_2}{d}$ 意义下的逆元,
对于方程两边同时乘 $inv$,
有 $k_1\%\frac{a_2}{d}=\frac{inv(b_2-b_1)}{d}$,
展开后有 $k_1=\frac{inv(b_2-b_1)}{d}+k_2\frac{a_2}{d}$,
代入开始的 $x=a_1k_1+b_1$,
有 $x=\frac{a_1inv(b_2-b_1)}{d}+k_2\frac{a_1a_2}{d}+b_1$,
把 $\frac{a_1a_2}{d}$ 看成新的 $a$,把 $\frac{a_1inv(b_2-b_1)}{d}+b_1$ 看成新的 $b$ 即可。
## 代码
[【模板】扩展中国剩余定理(EXCRT)](https://www.luogu.com.cn/problem/P4777)
``` cpp
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#define rg register
template<typename T>void read(rg T& x){
x=0;rg int fh=1;
rg char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
x*=fh;
}
const int maxn=1e5+5;
int n;
long long a[maxn],b[maxn];
long long gcd(rg long long aa,rg long long bb){
return bb==0?aa:gcd(bb,aa%bb);
}
long long lcm(rg long long aa,rg long long bb){
return aa/gcd(aa,bb)*bb;
}
long long exgcd(rg long long aa,rg long long bb,rg long long&xx,rg long long&yy){
if(bb==0){
xx=1,yy=0;
return aa;
}
rg long long nans=exgcd(bb,aa%bb,xx,yy);
rg long long t=xx;
xx=yy;
yy=t-aa/bb*yy;
return nans;
}
long long getinv(rg long long val,rg long long mod){
rg long long xx,yy;
exgcd(val,mod,xx,yy);
return (xx%mod+mod)%mod;
}
long long gsc(rg long long ds,rg long long zs,rg long long mod){
return ((unsigned long long)(ds*zs)-(unsigned long long)((long double)ds/mod*zs)*mod+mod)%mod;
}
int main(){
read(n);
for(rg int i=1;i<=n;i++) read(a[i]),read(b[i]);
rg long long newa,newb,tmp;
for(rg int i=2;i<=n;i++){
newa=lcm(a[i],a[i-1]),tmp=gcd(a[i],a[i-1]);
newb=gsc((b[i]-b[i-1])/tmp,getinv(a[i-1]/tmp,a[i]/tmp),newa);
newb=gsc(newb,a[i-1],newa)+b[i-1];
newb=(newb%newa+newa)%newa;
a[i]=newa,b[i]=newb;
}
printf("%lld\n",b[n]);
return 0;
}
```