zoukankan      html  css  js  c++  java
  • POJ 2891 Strange Way to Express Integers ★ (扩展欧几里德解同余式组)

    题目链接http://poj.org/problem?id=2891 题目大意: 很好的一道题,解同余式组: x = r1 (mod m1) x = r2 (mod m2) …… x = rp (mod mp)   思路: 因为m1, m2, m3, …… , mp不一定两两互素,所以不能直接用中国剩余定理. 不过,我们可以借用中国剩余定理的思想来解决这道题. 我们一个方程一个方程看, 先看第一个方程x = r1 (mod m1), 则最小的解为r1,满足方程的所有解为:x = r1 + k*m1. 我们现在再加第二个方程:x = r2 (mod m2), 根据上面的解可以变形一下方程:r1 + k*m1 = r2 (mod m2)  -> k * m1 = r2 - r1 (mod m2). 则可以根据扩展欧几里德算法求出k(形如Ax = B (mod C)的同余方程可由扩展欧几里德算法求出,因为它可以转化成ax + by = c的形式~~) 则满足前两个方程的解x就等于r1 + k * m1. 推广一下,如果我们知道了联立前p个方程的解Xp,那么加下一个方程时就可以变为Xp + k * lcm(m1, m2, …… , mp) = r(p+1) (mod m(p+1)),我们依旧可以用扩展欧几里德来求出k,借此求出联立前p+1个方程的解,直到联立完所有解. 无解的判断:当某个方程Xp + k * lcm(m1, m2, …… , mp) = r(p+1) (mod m(p+1))无解时,则整个方程组无解.  
    /*
    ①整个过程求解同于方程组
    x = a1 (mod m1)
    x = a2 (mod m2)
    ……
    x = ar (mod mr)
    (m1 m2 …… mr不必互素, (互素直接用中国剩余定理即可) )
    
    ②函数indeterminate_equation()求解不定方程ax + by = c  ->  AX = C (mod B)
    */
    
    #include 
    #include 
    using namespace std;
    void ext_gcd(long long a, long long b, long long &x, long long &y){
        if (b == 0){
            x = 1;
            y = 0;
            return ;
        }
        ext_gcd(b, a%b, x, y);
        long long tmp = x;
        x = y;
        y = tmp - a/b * y;
        return ;
    }
    long long gcd(long long a, long long b){
        return b ? gcd(b, a % b) : a;
    }
    long long lcm(long long a, long long b){
        return a / gcd(a, b) * b;
    }
    //求解不定方程ax + by = c  ->  AX = C (mod B)
    bool indeterminate_equation(long long a, long long b, long long c, long long &x, long long &y){
        int g = gcd(a, b);
        if (c % g != 0){
            return false;
        }
        a /= g;
        b /= g;
        c /= g;
        ext_gcd(a, b, x, y);
        x *= c;
        y *= c;
        //上面过程是求解出x ,y, 下面过程是求x的最小整数值
        long long tmp = abs(double(b));
        x = (x % tmp + tmp) % tmp;
        return true;
    }
    
    long long m[1010];
    long long r[1010];
    int main(){
        int k;
        while(cin >> k){
            long long mlcm = 1;
            int ok = 1;
            for (int i = 1; i <= k; i ++){
                cin >> m[i] >> r[i];
            }
            long long ans = r[1];
            for (int i = 2; i <= k; i ++){
                long long a = mlcm = lcm(mlcm, m[i-1]);
                long long b = m[i];
                long long c = r[i] - ans;
                long long x, y;
                if (indeterminate_equation(a, b, c, x, y)){
                    ans = ans + x * mlcm;
                }
                else{
                    cout << -1 << endl;
                    ok = 0;
                    break;
                }
            }
            if (ok)
                cout << ans << endl;
        }
        return 0;
    }
    
     
    举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
  • 相关阅读:
    今天是全面开发的第一天,特此纪念
    Linux 进程管理 (ZZ)
    骑车上班
    VSFTPD配置小结(一)
    Flash Builder 4 在Chrome的调试
    测试一下Windows Live Writer
    转:C++强大的背后
    转:Flex中的Image屬性 (width, contentWidth, content.width)的差異
    Flash Builder 4 安装提示“安装程序检测到计算机重新启动操作可能处于挂起状态“的解决
    使用简单工厂和State模式替换冗余的 switchcase 语句
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4113976.html
Copyright © 2011-2022 走看看