【LOJ2721】【NOI2018】屠龙勇士(CRT,扩展欧几里得)

Description

https://loj.ac/problem/2721


Solution

将题意转化成方程:

{ t 1 x a 1 ( mod p 1 ) t 2 x a 2 ( mod p 2 ) t 3 x a 3 ( mod p 3 )

对于每一个方程,我们可以用扩欧解出来,得到一个解 x i 和解的间隔 d i ,那么就可以将原方程转化成:

{ x x 1 ( mod d 1 ) x x 2 ( mod d 2 ) x x 3 ( mod d 3 )

然后两两合并、求解即可。

同步赛上有个东西忘记清零然后炸成70了QAQ


Code

/************************************************
 * Au: Hany01
 * Prob: dragon
 * Email: [email protected]
 * Inst: Yali High School
************************************************/

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
#define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define x first
#define y second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define ALL(a) (a).begin(), (a).end()
#define SZ(a) ((int)(a).size())
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia

template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }

inline LL read() {
    static LL _, __; static char c_;
    for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
    for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
    return _ * __;
}

const int maxn = 100005;

multiset<LL> Set;
struct Equation { LL c, m; }Eq[maxn];
int n, m, bk, N;
LL a[maxn], p[maxn], rew[maxn], t[maxn], A, B, C, t1, t2, Gcd, k, X, Y, d;

LL gcd(LL x, LL y, LL& a, LL& b)
{
    if (!x) { a = 0, b = 1; return y; }
    register LL ret = gcd(y % x, x, a, b),t = a;
    a = b - a * (y / x);
    b = t;
    return ret;
}

LL mult(LL a, LL b, LL MOD) {
    if (a < 0 && b < 0) a = -a, b = -b;
    if (b < 0) a = -a, b = -b;
    LL Ans = 0;
    for ( ; b; b >>= 1, (a <<= 1) %= MOD) if (b & 1) (Ans += a) %= MOD;
    return Ans;
}

int main()
{
    File("dragon");

    for (static int T = read(); T --; )
    {
        n = read(), m = read(), Set.clear(), bk = 0;
        For(i, 1, n) a[i] = read();
        For(i, 1, n) p[i] = read();
        For(i, 1, n) rew[i] = read();
        For(i, 1, m) Set.insert(read());
        For(i, 1, n) {
            if (*Set.begin() >= a[i]) t[i] = *Set.begin(), Set.erase(Set.begin());
            else {
                multiset<LL>::iterator it = --Set.upper_bound(a[i]);
                t[i] = *it, Set.erase(it);
            }
            Set.insert(rew[i]);
        }
        N = 0;
        For(i, 1, n) {
            if (p[i] == 1) continue;
            LL Gcd = __gcd(t[i], p[i]);
            A = t[i], B = p[i], C = a[i];
            if (C % (Gcd = __gcd(A, B))) { bk = 1; break; }
            k = C / Gcd, gcd(A, B, X, Y);
            d = p[i] / __gcd(p[i], t[i]);
            X = mult(X, k, d);
            Eq[++ N].c = X, Eq[N].m = d;
        }
        if (bk) { puts("-1"); continue; }

        Fordown(i, N, 2) {
            A = Eq[i - 1].m, B = -Eq[i].m, C = Eq[i].c - Eq[i - 1].c;

            if (C % (Gcd = __gcd(A, B))) { bk = 1; break; }
            k = C / Gcd, gcd(A, B, t1, t2);
            LL t = Eq[i - 1].m;
            Eq[i - 1].m = Eq[i - 1].m / __gcd(Eq[i - 1].m, Eq[i].m) * Eq[i].m;
            t1 = mult(t1, k, Eq[i - 1].m);
            Eq[i - 1].c = (mult(t1, t, Eq[i - 1].m) + Eq[i - 1].c) % Eq[i - 1].m;
        }

        if (bk) { puts("-1"); continue; }
        if (N) ((Eq[1].c %= Eq[1].m) += Eq[1].m) %= Eq[1].m;
        else Eq[1].m = 1, Eq[1].c = 0;
        For(i, 1, n)
            if (Eq[1].c * t[i] < a[i]) {
                Eq[1].c += (a[i] - Eq[1].c * t[i]) / t[i] / Eq[1].m * Eq[1].m;
                if (Eq[1].c * t[i] < a[i]) Eq[1].c += Eq[1].m;
            }
        printf("%lld\n", Eq[1].c);
    }

    return 0;
}
//叹江山如故,千村寥落。
//    -- 岳飞《满江红·登黄鹤楼有感》

猜你喜欢

转载自blog.csdn.net/hhaannyyii/article/details/81141200