中国剩余定理的应用及证明

中国剩余定理在ACM中主要用来解方程

中国剩余定理需要用到扩展欧几里得算法

就从欧几里得算法开始讲起

LL gcd(LL a,LL b)

{

    Return b==0?a:gcd(b,a%b);

}     

b==0时我们返回a作为最大公约数,现在就是判断ab的最大公约数是不是等于ba%b的最大公约数

ab=k……r

第一步:令c=gcd(a,b) 则设a=mc b=nc

第二步:根据前提r=a-kb=mc-knc=(m-kn)c

第三步:根据第二步结果可知c也是的因数

第四步:判定m-knn互质(否则,可设m-kn=xdn=yd d>1,则m=kn+xd=kyd+xd=(ky+x)d,则a=mc=(ky+x)dc b=nc=ycd ab的最大公约数成为cd,与前面矛盾)

 

 

然后是扩展欧几里得算法

LL exgcd(LL a,LL b,LL &x,LL &y)

{

    if(b==0)

    {

        x=1;

        y=0;

        return a;

    }

    LL gcd=exgcd(b,a%b,x,y);

    LL tmp=x;

    x=y;

    y=tmp-a/b*x;

    return gcd;

}

扩展欧几里得算法用于求解ax+by=gcd(a,b)中的xy

怎么求解呢

利用前面的性质gcda,b)=gcdb,a%b)

ax+by=gcd(a,b)=gcd(b,a%b)=b*x1+a%b*y1

我们可以把a%b写成 (a-a/b*b) 代入上式

ax+by=b*x1+(a-a/b*b)*y1=a*y1+b*(x1-a/b*y1)

对比系数得出 x=y1 y=x1-a/b*y1

故而我们可以写出上述递归函数求解x

我们在b=0的时候返回x=1 y=0 这个列个式子 很好理解的 就不写了

 

 

 

然后就是应用扩展欧几里得定理求解线性同余方程组了

 

        a1=a[0];b1=b[0];

        for(int i=1;i<m;i++)

        {

            a2=a[i];b2=b[i]; 

            LL gcd=exgcd(a1,a2,x,y);

            if((b2-b1)%gcd)

            {

                flag=1;

                break;

            }

            LL t=a2/gcd;

            x=(x*(b2-b1))/gcd;

            x=(x%t+t)%t;

            b1=a1*x+b1;

            a1=(a1*a2)/gcd;

            b1=(b1%a1+a1)%a1;

        }

N=ai (mod bi)

我们取两组数来从小见大吧

N mod a1=b1

N mod a2=b2

可以改写成

N=a1*x+b1

N=a2*y+b2

我们求解出x或者y中的任意一个就可以求得解了

a1*x+b1=a2*y+b2 移项

a1*x-a2*y=b2-b1……1

是不是和之前写的扩展欧几里得算法很像

a*x1+b*y1=gcd(a,b)……2

我们从这里引入扩展欧几里得算法的应用求解ax+by=c的整数解(整数解存在的前提是c|gcd(a,b) c%gcd(a,b)==0

结合2式很容易得出 1式中x=(b2-b1)/gcd(a1,a2)*x1(为什么a2可以变成正的,无非就是y换个正负号么。。)

这样我们就得出了方程1 x的一个解 但x未必是最小的正解

我们可以得出 设我们上面得出的解为x0 y0

那么通解可以表示为 x=x0+(a2/gcd)*t

                   y=y0+(a1/gcd)*t 其中gcd=gcd(a1,a2)

于是我们去求最小的正数x t=a2/gcd x=(x%t+t)%t

然后最终N的值就是a1*x+b1 我们把它保存在b1中 然后a1lcm(a1,a2) 得到最小的正数b1 b1=(b1%a1+a1)%a1 这样我们就得到了最终的答案 a1是循环节 b1是最小的正数N

 

你可能感兴趣的:(中国剩余定理的应用及证明)