已知一系列除数和模数,求最小的满足条件的数
我们先考虑一般的情况,即模数不互质。(扩展中国剩余定理)
我们考虑两个方程的情况
x%M=R x=k1∗M+Rx=k1 * M+Rx=k1∗M+R
x%m=r x=k2∗m+rx=k2 * m+rx=k2∗m+r
所以k1∗M+R=k2∗m+rk1 * M+R=k2 * m+rk1∗M+R=k2∗m+r
即k1∗M−k2∗m=r−Rk1 * M-k2 * m=r-Rk1∗M−k2∗m=r−R
我们可以用扩展欧几里得求出k1,求出一个x
X的解系为X=x+k∗lcm(M,m)X=x+k*lcm(M,m)X=x+k∗lcm(M,m)
即将原来的两个方程变成了一个方程X%lcm(M,m)=x
剩下要做的就是不断将方程进行合并合并成一个,再按要求输出
由以上得到算法
bool mod_equation(ll n,ll &M,ll &R)
{ll m,r;scanf("%lld%lld",&M,&R);bool flag=true;for(int i=1;i<n;i++){scanf("%lld%lld",&m,&r);if(flag){ll k1,k2,C=r-R,d;ex_gcd(M,m,d,k1,k2);if(C%d) {flag=false; continue;}k1=C/d*k1%(m/d); R+=k1*M; M=M/d*m; R%=M;}}R=(R%M+M)%M;return flag;
}
一个小问题是ax+by=gcd(a,b)的解系为x+b/d * k,y-a/d * k
而ax+by=c的一个解为x*=c/d y*=c/d,解系仍然为x+b/d * k,y-a/d * k,也就是说解系只和系数有关系而和等式右边没有关系
当模数互质的时候,我们不必要这样做,可以直接构造出答案。
假设模数分别为m1,m2,…,mk,且(m1,m2,…,mk)=1,我们令M=lcm(m1,m2,…,mk),ti为M/mi模mi的逆元,那么有一个答案为
所有的答案为X=x+k*M
直觉上理解的话,x中M/mj模mi肯定是0,只有M/mi这项为ai
因此直接计算答案,逆元用扩展欧几里得求解
bool mod_equation(ll n,ll &M,ll&R)
{M=1; ll t,d,k,x=0;for(int i=1;i<=n;i++) M=M*m[i];for(int i=1;i<=n;i++){ex_gcd(M/m[i],m[i],d,t,k);t=(t%m[i]+m[i])%m[i];x=(x+t*M/m[i]*r[i])%M;}R=(x%M+M)%M;return true;
}