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;
}
 
posted @ 2013-01-06 23:44  AbandonZHANG  阅读(113)  评论(0编辑  收藏  举报