excrt
摘自蓝书
考虑使用数学归纳法,假设已经求出了前 \(k-1\) 个方程构成的方程组的一个解 \(x\)。记 \(m= lcm (m_1,m_2,...,m_{k-1})\),则 \(x+i*m(i\in Z)\) 是前面方程组的一个通解。
简单证明下。
\[x\equiv a_i \pmod{m_i}
\]
因为有
\[m_i|m
\]
所以
\[x+i*m\equiv a_i \pmod{m_i}
\]
考虑第 \(k\) 个方程,求出一个整数 \(t\),使得 \(x+t*m\equiv a_k \pmod{m_k}\)。exgcd 直接做就好了,注意要求出 \(x\) 的最小解(https://www.luogu.com.cn/blog/McHf/p5656-exgcd)
#include <bits/stdc++.h>
#define int __int128
#define pb push_back
using namespace std;
int rd() {
int f=1,sum=0; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return sum*f;
}
void pr(int x) {
if(x<0) {putchar('-');x=-x;}
if(x>9) pr(x/10);
putchar(x%10+'0');
}
const int N=(int)(1e5+5);
int A[N],m[N],n,x,y;
void exgcd(int a,int b) {
if(!b) {
x=1; y=0; return ;
}
exgcd(b,a%b);
int x1=0,y1=0;
x1=y; y1=x-(a/b)*y;
x=x1; y=y1;
}
inline int lcm(int x,int y) {
return x/__gcd(x,y)*y;
}
signed main() {
cin.tie(0); ios::sync_with_stdio(false);
n=rd();
for(int i=1;i<=n;i++) m[i]=rd(),A[i]=rd();
int ans=A[1],M=m[1];
bool fl=1;
for(int i=2;i<=n;i++) {
int a=M,b=m[i],C=(A[i]-ans%b+b)%b;
int d=__gcd(a,b);
if(C%d) {
fl=0; break ;
}
exgcd(M,m[i]);
x=x*(C/d)%(m[i]/d);
ans+=x*M; M=lcm(M,b);
ans=(ans%M+M)%M;
}
pr((ans%M+M)%M);
return 0;
}