同余模方程学习小记

什么是同余模呢?比如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;

}

  

 

你可能感兴趣的:(学习)