exCRT 学习笔记
exCRT用来求解方程组
\[\begin{cases}x\equiv a_1\pmod {b_1}\\x\equiv a_2\pmod {b_2}\\...\\x\equiv a_n\pmod {b_n}\end{cases}
\]
此时不需要满足 \(b_1\text{~}b_n\) 互质
解法:
尝试将 \(n\) 个方程组合并成一个
首先发现:
\(\begin{cases}x\equiv a_1\pmod {b_1}\\x\equiv a_2\pmod {b_2}\\\end{cases}\)
合并之后 \(b\) 一定为 \(lcm(b1,b2)\)
然后考虑 \(a\):
可以发现 \(x=a_1+k_1\times b_1=a_2+k_2\times b_2\)
\(k_1\times b_1-k_2\times b_2=a_2-a_1\)
未知数只有 \(k\) 显然可以exgcd求出(当然如果 \(\gcd(b1,b2)\nmid(a_2-a_1)\) 无解)
然后 \(x=a_1+k_1\times b_1\) 当做合并后的 \(a\) 即可
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define int __int128
#define gc getchar
#define pc putchar
const int N=1e7+5;
const int M=4e2+5;
const int inf=0x7fffffff;
const int mod=1e6+3;
inl int read(){
int x=0,f=1;char c=gc();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x*f;
}
inl void write(int x){
if(x<0){pc('-');x=-x;}
if(x>9)write(x/10);
pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m;
inl void exgcd(int a,int b,int &x,int &y){
if(!b)return x=1,y=0,void();
exgcd(b,a%b,y,x);
y-=(a/b)*x;
}
inl int gcd(int a,int b){return !b?a:gcd(b,a%b);}
inl int lcm(int a,int b){return a*b/gcd(a,b);}
signed main(){
n=read();
int b1=read(),a1=read();
for(int i=2;i<=n;i++){
int b2=read(),a2=read();
int d=gcd(b1,b2);
if((a2-a1)%d){puts("-1");return 0;}
int x,y;
exgcd(b1,b2,x,y);
int mod=lcm(b1,b2);
a1=(a1+(a2-a1)/d*x%mod*b1%mod+mod)%mod;
b1=mod;
}
writel(a1);
return 0;
}