中国剩余定理

中国剩余定理,是建立在扩展欧几里得上的算法
用来求线性模方程的解
即给出许多模数mi,然后给出余数ai,求原数x
代码如下

struct China{
    #define N 5
    LL A[N],p[N],T[N],m[N],T1[N],M;
    int n;
    void exgcd(LL a,LL b,LL &x,LL &y){
        if(!b){x=1;y=0;return;}
        exgcd(b,a%b,y,x);y-=x*(a/b);
    }
    void init(){n=0;}
    void insert(LL a,LL b){p[++n]=a,A[n]=b;}
    LL Solve(){
        LL ans=0;
        M=1;FOR(i,1,n)M*=p[i];
        FOR(i,1,n){
            m[i]=M/p[i];
            exgcd(m[i],p[i],T[i],T1[i]);
            ans=(ans+T[i]*m[i]*A[i]%M+M)%M;
        }
        return ans
    }
}T;

上述代码是建立在各除数互质的情况下
若各除数不互质,可采用下段代码
推导如下:

x%m1=a1 x%m2=a2

a2+m2*k2=a1+m1*k1

m1*k1-m2*k2=a2-a1 d=gcd(m1,m2)

A=m1/d,B=m2/d,C=(a2-a1)/d

A*k1+B*k2=C

k1=(k1*C%B+B)%B

ans=m1*k1+a1

FOR(i,1,n-1){
    LL d=gcd(p[i],p[i+1]),C=A[i+1]-A[i];
    if(C%d)return -1;
    LL a1=p[i]/d,a2=p[i+1]/d;
    C/=d;
    LL k1=Exgcd(a1,a2,C);
    p[i+1]=a1*a2*d;
    A[i+1]=A[i]+a1*d*k1;
}
return A[n];

你可能感兴趣的:(算法,——数论,算法和数据结构模板)