zoukankan      html  css  js  c++  java
  • 同余模方程学习小记

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

      

     
  • 相关阅读:
    庆祝一下开通了第一条博客!
    查看树莓派温度
    Ubuntu Server for Raspberry Pi部署Jenkins
    acme.sh部署RSA、ECC双证书(使用阿里云API)
    Ubuntu Server 20.04换用阿里源
    ESP32使用NTP同步时间
    C语言的可变参数函数
    一种Θ(1)的计算32位整数二进制中1的个数的方法
    CentOS 8安装Docker
    CentOS 8搭建LNMP + WordPress(三)
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/3446728.html
Copyright © 2011-2022 走看看