POJ-2891 Strange Way to Express Integers 中国剩余定理

这题是一道非常直接的中国剩余定理的题目,但是这里的不同的给定的几个数不一定是互质的。因此也就不能直接用解中国剩余定理的方法来求了。

我们通过迭代法来求解最后的答案。

设有 x = 1(mod 5)

   y = 2(mod 6)

   z = 3(mod 7)

那么根据第一个方程我们设 x = 5t+1, 代入到第二个方程 5t+1 = 2(mod 6)  ==> 5t -6u = 2-1 左边这个式子就可以用扩展GCD求出t的解,我们知道t的解由两部分组成,一部分是我们解出来的一般解5(必须保证为最小的正整数),此时u等于4,另外的就是加上 k 个 6 / gcd(5, 6)了,那么我们可以得到 t = 5 + 6k,再将这个值代入到第一个式子我们就将得到一个新的表达式,x = 26(mod 30),得到这个式子是非常有用的,首先如果后面还有式子的话,那么我们将这个式子和下一个式子进行求解,如果后面没有了式子,那么我们又注意到由于保证了x为最小的正整数,所以此时令k=0,代入之后的26就是直接满足这两个方程的最小值。

代码如下:

#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long int Int64;

int N;

Int64 ext_gcd(Int64 a, Int64 b, Int64 &x, Int64 &y)
{
    int temp, ret;
    if (!b) {
        x = 1, y = 0;
        return a;
    }
    ret = ext_gcd(b, a % b, x, y);
    temp = x, x = y, y = temp - a/b*y;
    return ret;
}

int main()
{
    int flag;
    Int64 ai, bi, a, b, g, x, y, ret, temp;
    while (scanf("%d", &N) == 1) {
        flag = ret = 0;
        scanf("%lld %lld", &a, &b);
        for (int i = 2; i <= N; ++i) {
            scanf("%lld %lld", &ai, &bi);
            if (flag) {
                continue;
            }
            g = ext_gcd(a, ai, x, y);  // 求得特解 x
            if ((bi - b) % g != 0) {
                flag = 1;
                continue;
            }
            x *= (bi - b) / g;
            x %= (ai / g);
            if (x < 0) {
                x += ai / g;
            }
            b = a * x + b;
            a = a * ai / g;
        }
        if (flag) {
            puts("-1");
            continue;
        }
        printf("%lld\n", b);
    }
    return 0;
}
posted @ 2012-07-21 18:08  沐阳  阅读(338)  评论(0编辑  收藏  举报