• 洛谷 P1516 青蛙的约会


    题目链接

    Solution

    先列出最简单的柿子:

    [(X+mT) \% L=(Y+nT) \% L ]

    下面推导过程:

    [(X + mT) \% L = (Y + nT) \% L ]

    [⇒ X + mT equiv Y + nT (\%L) ]

    [⇒ (m-n)T equiv Y-X (\% L) ]

    其中 (m-n), (Y-X) 已知,分别设为 (a), (c), 上面的柿子可以写成如下形式:

    [aT + yL = c ]

    如果用 (x) 表示 (T)(b) 表示 (L),这个柿子还可以变成更优美的形式:

    [ax + by = c ]

    [(a=m-n, b=L, c=Y-X) ]

    这就变成线性同余方程的一般柿子了。

    考虑用 exgcd 求出一组对于 (ax+by=gcd(a,b)) 的特解,记为 (x_0), (y_0)。显然:

    [ax_0+by_0=gcd(a, b) ]

    [⇒ ax_0 frac{c}{gcd(a,b)} +by_0 frac{c}{gcd(a,b)} = gcd(a,b) frac{c}{gcd(a,b)} ]

    [⇒ a frac{x_0c}{gcd(a,b)} + b frac{y_0c}{gcd(a,b)} = c ]

    于是我们对原方程求出了一组特解:

    [x = frac{x_0c}{gcd(a,b)}, y = frac{y_0c}{gcd(a,b)} ]

    考虑通解。设 (x, y) 是已求出的特解,则有:

    [ax+by=a(x+bd)+b(y-ad) ]

    要使 (bd, ac) 最小且为整数,(d) 的最小值为 (frac{1}{gcd(a,b)})。因此:

    [x_{min}=x \% frac{b}{gcd(a,b)} ]

    注意负数取模。

    另外,如果计算前 (a) 是负数,就对 (a)(c) 取相反数。

    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    
    long long X, Y, m, n, l, a, b, c, x, y, g;
    
    long long gcd(long long x, long long y) { return y == 0 ? x : gcd(y, x % y); } 
    
    void exgcd(long long a, long long b)
    {
        if(b == 0)
        {
            x = 1, y = 0;
            return ;
        }
        exgcd(b, a % b);
        long long tx = x;
        x = y, y = tx - (a / b) * y;
    }
    
    int main()
    {
        scanf("%lld%lld%lld%lld%lld", &X, &Y, &m, &n, &l);
        a = m - n, b = l, c = Y - X, g = gcd(a, b);
        if(a < 0) a = -a, c = -c;
        g = gcd(a, b);
        if(c % g != 0) { printf("Impossible"); return 0; }
        exgcd(a, b);
        printf("%lld", ((x * (c / g)) % (b / g) + (b / g)) % (b / g));
        return 0;
    }
    
  • 相关阅读:
    缓存
    json集合取值
    四个div块点击某个突出显示
    table获取某一列的td
    鼠标悬浮tr追加背景颜色
    jquery弹出层
    面试题
    表单校验及正则表达式
    jquery操作DOM
    jquery的事件与动画
  • 原文地址:https://www.cnblogs.com/Andy-park/p/13740947.html
Copyright © 2020-2023  润新知