什么是同余模呢?比如21%6=3,21%8=5,21%11=10,就是给出(6,3)(8,5)(11,10)这样的数对来求一个最小的正整数X,满足:
X%6=3;
X%8=5;
X%11=10。
怎么解决这个问题呢?首先我们将这样的数对表示为(m,r),设有两个(m1,r1),(m2,r2),设答案为X,那么显然有X=m1*k1+r1,X=m2*k2+r2 ,因此得到:m1*k1+r1=m2*k2+r2,即:m1*k1-m2*k2=r2-r1。设x=k1,y=-k2,c=r2-r1,上式即为:m1*x+m2*y=c。我们可以用扩展欧几里得求出x和y以及m1和m2的最大公约数d,如果c不能整除d则显然这样的x和y是不存在的。下面的讨论我们假设c能够整除d.我们知道我们求出x和y满足:m1*x+m2*y=d。那么我们可以求出x0和y0满足m1*x0+m2*y0=c,显然x0=c/d*x,y0=c/d*y,并且我们知道,X、Y的通项公式为:
X=x0+(m2/d)*k
Y=y0-(m1/d)*k
因此为求出最小的正整数X,我们总能用m2/d来调节x0使X最小。那么,若给出的是超过两组的(m,r)呢?这样解决:将r0=X(X就是用前两组求出的X),m0=m1*m2/d(即m0是m1和m2的最小公倍数),那么若有超过两组的(m,r),最后的答案ans必满足:ans%m0=r0。因为ans=m0*k+r0,因此ans%m1=(m0*k+r0)%m1=r0%m1=X%m1=r1,同理对(m2,r2)也是。这样我们就将前两组合并成新的一组(m0,r0)。这样就懂了吧,只要依次合并,
//m1、m2、……mk不一定两两互质。
//参数:m[i]:k个不一定两两互质的数。
// a[i]:X模mi的余数。
//返回:有解返回true,答案在a[1] 中;
// 无解返回false。
i64 a[15],m[15];
int n;
i64 exGcd(i64 a,i64 b,i64 &x,i64 &y)
{
i64 t,d;
if(!b)
{
x=1;
y=0;
return a;
}
d=exGcd(b,a%b,x,y);
t=x;
x=y;
y=t-a/b*y;
return d;
}
bool modular1(i64 a[],i64 m[],int k)
{
i64 d,t,c,x,y,i;
for(i=2;i<=k;i++)
{
d=exGcd(m[1],m[i],x,y);
c=a[i]-a[1];
if(c%d) return false;
t=m[i]/d;
x=(c/d*x%t+t)%t;
a[1]=m[1]*x+a[1];
m[1]=m[1]*m[i]/d;
}
return true;
}