zoukankan      html  css  js  c++  java
  • 中国剩余定理(模数不互质)

    上一篇博客写的是中国剩余定理模数不互质的情况,然鹅——还存在着模数互质的情况,而原来的做法就没有办法用了

    那我们现在该怎么做呢?


    原来的思路是对于每一个方程,我们找出一个基础数,使得基础数满足该方程要求。因为是互质的关系,所以所有基础数加起来也不会冲突。(这个由最小公倍数保证)

    还是这个栗子 存在一个数x,除以3余2,除以5余3,除以7余2,然后求这个数

    3的基础数是35,满足除以3余2,而且是5和7的倍数,5,7同理。也就是说:基础数几倍几倍的变化是不会造成突然冒出来一个什么数%5或%7出现了余数


    而现在模数不互质,还是举个栗子存在一个数x,除以6余4,除以8余2,除以9余7,然后求这个数

    答案手推出来是34,如果仍然按照原来的做法lcm为72,6的基础数为。。。诶诶?怎么推不出来?72/6=12,ok,12不满足,再扩大,emm,还是不满足,再扩大。。。

    好吧,相信大家已经发现了!12是6的倍数啊!再怎么扩大也不可能满足条件啊!

    这就是互质与不互质的区别:不互质可能会导致基础数是模数的倍数,那么这个算法就凉凉了

    那就让我们换一个思维方式吧!

    可以先对第一个方程求解出一个满足条件的x,再去看下一个方程,在这个x的基础上,加上一个满足下一个方程的x',同时不破坏前面方程的要求。

    也就是说,我们去判断一个方程有没有解,解是多少。这,这不就是扩欧吗?

    具体看代码吧~

    #include<bits/stdc++.h>
    using namespace std;
    int a[10],m[10],tong[103];
    int exgcd(int a,int &x,int b,int &y)
    {
        if(b==0){x=1;y=0;return a;}
        int x2,y2;
        int gcd=exgcd(b,x2,a%b,y2);
        x=y2;
        y=x2-a/b*y2;
        return gcd;
    }
    int main()
    {
        freopen("crt.in","r",stdin);
        freopen("crt.out","w",stdout);
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n;
            scanf("%d",&n);
            scanf("%d%d",&a[1],&m[1]);
            //用lcm求当前到达过的方程中,所有模数的lcm,sum是最后的结果,但是每一次都会用
            //解出的x去更新它,fail判断是否有解 
            int lcm=m[1],sum=a[1],fail=0;
            for(int i=2;i<=n;i++)
            {
                int x,y;
                scanf("%d%d",&a[i],&m[i]);
                a[i]=((a[i]-sum)%m[i]+m[i])%m[i];//sum就是要求的x,不断更新 
                int d=exgcd(lcm,x,m[i],y);//lcm*x+m[i]*y+sum=a[i]才能保证x%m[i]=a[i] 
                if(a[i]%d==0) x=x*(a[i]/d)%m[i];
                else fail=1;
                sum+=x*lcm;//注意是乘lcm哦!不然可能会出现前面的方程冲突 
                lcm=lcm/d*m[i];//到现在这一个方程了,所有模数的最小公倍数 
                sum=(sum%lcm+lcm)%lcm;
            }
            if(fail) printf("No
    ");
            else printf("%d
    ",sum); 
        }
    }
    /*
    3
    4 6
    2 8
    7 9
    
    3
    2
    3 5
    4 7
    3
    4 6
    2 8
    7 9
    2
    1 2
    2 4
    */
  • 相关阅读:
    安装go版本
    golang简介
    安装MySQL
    art.dialog.art 中,将子页面窗口中的值传递给父框架中
    Windows7下安装CentOS
    生成uuid
    如何开启win7端口的图文教程
    PHPMailer不能发送邮件
    sql 如果关联表 没有值 设置 默认值
    php array 分页
  • 原文地址:https://www.cnblogs.com/yyys-/p/10473574.html
Copyright © 2011-2022 走看看