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
  • 相关阅读:
    前端性能优化
    web缓存
    js实现数组去重并且显示重复的元素和索引值
    前端面试简单整理
    js记录重复字母的个数
    js数组快速排序
    sql数据库链接
    w3cschool -css
    w3cschool -html
    A*算法在栅格地图上的路径搜索(python实现)
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4694361.html
Copyright © 2011-2022 走看看