【数学】欧几里得算法

验证链接:洛谷P5656 | 洛谷P1082 | 洛谷P3811

LCE1这个算法找到的是x的最小非负整数解。剩下的事情交给倍增算法。

注意特判0和负数的情况,下面存在除以0的时候。假如传入的数字有负数,则返回值需要特殊处理。

namespace exGCD {

    ll exgcd(ll a, ll b, ll &x, ll &y) {
        if(b == 0) {
            x = 1, y = 0;
            return a;
        }
        ll d = exgcd(b, a % b, x, y), t;
        t = x, x = y, y = t - a / b * y;
        return d;
    }

    // ax + by = c
    int LCE1(ll a, ll b, ll c, ll &x, ll &y, ll &dx, ll &dy) {
        ll d = exgcd(a, b, x, y), t = b / d;
        if(c % d != 0) {
            // no solution
            x = -1, y = -1, dx = -1, dy = -1;
            return -1;
        }
        // solution is: x = x + k * dx, y = y - k * dy
        x = ((x % t) * (c / d % t) % t + t) % t;
        y = (c - a * x) / b, dx = t, dy = a / d;
        return 0;
    }

    // ax = r mod m
    int LCE2(ll a, ll r, ll m, ll &x, ll &dx) {
        ll y, d = exgcd(a, m, x, y), t = m / d;
        if(r % d != 0) {
            // no solution
            x = -1, dx = -1;
            return -1;
        }
        // solution is: x = x + k * dx
        x = ((x % t) * (r / d % t) % t + t) % t, dx = t;
        return 0;
    }

    ll inv(ll a, ll m) {
        ll x, y, d = exgcd(a, m, x, y);
        if(d != 1) {
            // no solution
            return -1;
        }
        x = (x % m + m) % m;
        // solution is: x = x + m / d
        return x;
    }

}
posted @ 2020-11-27 02:03  purinliang  阅读(125)  评论(0编辑  收藏  举报