zoukankan      html  css  js  c++  java
  • POJ 2891 扩展欧几里德

    这个题乍一看跟剩余定理似的,但是它不满足两两互素的条件,所以不能用剩余定理,也是给了一组同余方程,找出一个X满足这些方程,如果找不到的话就输出-1

    因为它不满足互素的条件,所以两个两个的合并,最后合成一个。

    题目给定的是

    M % m1 = r1

    M % m2 = r2

    ......

    M % mn = rn

    只需将两个式子合并成一个式子,那么这个合并的这个式子就可以继续和下面的式子继续合并,知道合到最后一个式子。

    首先来看下两个式子怎么合并。

    M % m1 = r1    可以写成  M = k1 * m1 + r1;

    同理M =  k2 * m2 + r2

    所以k1 * m1 + r1  = k2 * m2 + r2

    k1 * m1 - k2 * m2 = r2 - r1

    将k1 看成x, m1看成a, k2看成y, m2看成b, r2 - r1看成c

    那么这个式子就变成了

    ax-by=c;不定方程

    这时候就可以用不定方程来解了。

    因为题目给的两两可能不互素,所以gcd(a, b) 有可能不等于1,所以,这个方程不一定有解,所以就是判断这个题有没有解的条件。

    如果有解的话,用扩展欧几里德可以的出这个方程的解,然后将x带入到 k1 * m1 + r1中得到M,这时候M就是这两个方程组的一个特解,通解就是M' = M + K * LCM(m1, m2);

    这个式子可以变化成M' % LCM(m1, m2) = M;所以又可以继续跟下面的式子合并了。所以这个式子对应的余数r就是M, 模数(就是式子中的mi)就是LCM(m1,m2);

    到这里之后就合并好了一个式子。下面就是继续按照这个过程合并到第n个式子了。最后合并完之后就剩下一个式子,求出来的M就是方程组的特解,通解为M' = M + k * LCM; 其中LCM = LCM(m1, m2...mn), 最小正整数解为(M %  LCM + LCM) % LCM;

    还有一个坑就是如果边输入边处理的话,不要找到无解立马就跳出循环,因为后面的数据还没输入完。

    代码如下:

        /*************************************************************************
            > File Name: 5.cpp
            > Author: Howe Young
            > Mail: 1013410795@qq.com 
            > Created Time: 2015年08月01日 星期六 15时39分47秒
         ************************************************************************/
    
        #include <iostream>
        #include <cstdio>
        using namespace std;
        const int maxn = 1e5 + 5;
        typedef long long ll;
        ll m[maxn], r[maxn];
        ll exgcd(ll a, ll b, ll &x, ll &y)
        {
            if (b == 0)
            {
                x = 1;
                y = 0;
                return a;
            }
            ll r = exgcd(b, a % b, x, y);
            ll t = x;
            x = y;
            y = t - a / b * y;
            return r;
        }
        int main()
        {
            int k;
            while (~scanf("%d", &k))
            {
                for (int i = 1; i <= k; i++)
                    scanf("%lld %lld", &m[i], &r[i]);
                ll m1, m2, r1, r2, c, d;
                m1 = m[1]; r1 = r[1];
                bool flag = true;
                for (int i = 2; i <= k; i++)
                {
                    ll x, y;
                    d = exgcd(m1, m[i], x, y);
                    if ((r[i] - r1) % d != 0)
                    {
                        flag = false;
                        break;
                    }
                    c = r[i] - r1;
                    x = c / d * x % (m[i] / d);
                    r1 = m1 * x + r1;
                    m1 = m1 / d * m[i];
                    r1 %= m1;
                }
                if (!flag)
                {
                    printf("-1
    ");
                    continue;
                }
                r1 = (r1 + m1) % m1;
                printf("%lld
    ", r1);
            }
    
            return 0;
        }
    View Code
  • 相关阅读:
    centos7.6 使用yum安装mysql5.7
    解决hadoop本地库问题
    docker-compose 启动警告
    docker 安装zabbix5.0 界面乱码问题解决
    docker 部署zabbix问题
    zookeeper 超时问题
    hbase regionserver异常宕机
    (转载)hadoop 滚动升级
    hadoop Requested data length 86483783 is longer than maximum configured RPC length
    zkfc 异常退出问题,报错Received stat error from Zookeeper. code:CONNECTIONLOSS
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4694361.html
Copyright © 2011-2022 走看看