zoukankan      html  css  js  c++  java
  • POJ2891 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;
    }
  • 相关阅读:
    软阈值迭代算法(ISTA)和快速软阈值迭代算法(FISTA)
    伍德伯里矩阵恒等式(Woodbury matrix identity)
    压缩感知:一种新型亚采样技术
    运输层--------运输层与网络层的关系、UDP、TCP
    单链表的基本操作(二)
    单链表的基本操作(一)
    c++中的数据类型转换
    链表总的首元结点、头结点、头指针的区别
    封装设计基础知识点
    git的使用总结
  • 原文地址:https://www.cnblogs.com/Lyush/p/2602617.html
Copyright © 2011-2022 走看看