中国剩余定理(除数互质版)

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


你可能感兴趣的:(小模板)