x%mod[1]=a[1]
x%mod[2]=a[2]
x%mod[3]=a[3]
...
已知mod之间相互互质,求解最小的x。
中国剩余定理就是用于求解此类问题。
反过来想,假设最小解为 x , mod 的最小公倍数为 Lcm ,可以很容易地想到通解为: x+Lcm*k(k>=0且为整数) 。
因为对于 (x+Lcm*k)%mod[i]=x%mod[i]+Lcm*k%mod[i], i为任意值的时候,因为 Lcm 为所有 mod 的 最小公倍数,所以后一项一定是为 0 的,方程仍然成立。
想通了以上步骤,其实中国剩余定理就是通过一连串的计算解出某一个特解,然后减去多余的 Lcm ,即为最小的解 x 。
假设 x[1]%mod[1]=a[1]
x[2]%mod[2]=a[2]
x[3]%mod[3]=a[3]
...
特解 S 一定可以拆成多个数的和,就假设 x[i] 为特解的某一项,对于当前的 x[i] ,需要满足 x[i]%mod[i]=a[i] ,并且 x[i]%mod[j]=0 (对于任意 i != j ) ,这样的话 x[i] 全部相加才不会相互影响。可以想到当前的 x[i] 一定为所有 mod[j] ( j != i ) 乘积的倍数,所以只需要在 mod[j] ( j != i ) 乘积的倍数中找到一个满足 x[i]%mod[i]=a[i] 的数即可。
假设所有 mod[i] 的乘积为 M , mod[j] ( j != i ) 乘积就为 M/mod[i] 。
对于求解的方法,有一个小技巧。如果能够找到一个数 s%mod[i]=1,对于需要求解的 x[i]%mod[i]=a[i] ,可以得到 x[i]=s*a[i] 。因为所有的 mod[i] 两两互质,所以 mod[i] 与 M/mod[i] 也互质 (这里即为此方法只能处理除数互质的原因) ,求解 s 的话,可以写出方程
(M/mod[i])*x+mod[i]*y=1 //可以看出这是扩展欧几里得的一般式
(M/mod[i])*x=1-mod[i]*y
(M/mod[i])*x%mod[i]=(1-mod[i]*y)%mod[i]=1
所以可以得到 s=M/mod[i]*x ,x[i]=s*a[i]=M/mod[i]*x*a[i]。
代码:
int x,y,n,mod[1005],a[1005];
int exgcd(int a,int b)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int gcd=exgcd(b,a%b);
int mid=x;
x=y;
y=mid-a/b*y;
return gcd;
}
int fun(int mod[],int a[],int n)//n为方程个数
{
int M=1;
for(int i=0;i<n;i++)
M*=mod[i];
int sum=0,Lcm=1;
for(int i=0;i<n;i++)
{
int mid=M/mod[i];
int gcd=exgcd(Lcm,mod[i]);
Lcm=Lcm*mod[i]/gcd;
exgcd(mid,mod[i]);
sum=(sum+x*mid*a[i])%M;
}
return (sum+Lcm)%Lcm;
}