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;

}

你可能感兴趣的:(Integer)