模线性方程组(中国余数定理)
题意:给定了n组除数m[i]和余数r[i],通过这n组(m[i],r[i])求解一个x,使得x mod m[i] = r[i]。
直接用中国余数定理,n个m[i]相乘,可能会超出longlong范围
做法:
从n=2开始递推
x mod m[1] = r[1]
x mod m[2] = r[2]
即存在
x = m[1] * k[1] + r[1]
x = m[2] * k[2] + r[2]
推出
m[1] * k[1] - m[2] * k[2] = r[2] - r[1]
可用扩展欧几里德求出k[1]进而求出x,那么
一开始的两个式子即可合并为
X mod lcm(m[1], m[2]) = x (lcm为最小公倍数)
for(i=1;i<=n;i++){
scanf("%lld%lld",&m[i],&r[i]);
}
m[0]=m[1];
r[0]=r[1];
for(i=2;i<=n;i++){
ll k1,k2,c;
c=r[i]-r[0];
ll gcd=ext_gcd(m[0],m[i],k1,k2);
if(c%gcd){
ans=-1;
break;
}
m[i]/=gcd;
c/=gcd;
k1=(k1*c)%m[i];
if(k1<0)
k1+=m[i];
r[0]=m[0]*k1+r[0]; // x
m[0]=m[0]*m[i]; // 最小公倍数
ans=r[0];
}