「NOI 2018」屠龙勇士「扩展中国剩余定理」

版权声明:本文为hzy原创文章,未经博主允许不可随意转载。 https://blog.csdn.net/Binary_Heap/article/details/82149212

题目传送门

题解

首先,每条龙使用哪把剑是确定的,我们可以根据题意使用 m u l t i s e t (可重集)求出.

#include <iostream>
#include <cstdio>
#include <cmath>
#include <set>
using namespace std;

#define For(i, j, k) for(int i = (j), r__ = (k); i <= r__; i ++)

typedef long long LL;

const int MAXN = 1e5 + 2;

static int n, m;
static int gatk[MAXN], sw[MAXN];
static LL a[MAXN], p[MAXN];
multiset<int> sword;

LL gcd(LL a, LL b) {
    return b == 0 ? a : gcd(b, a % b);
}

void exgcd(LL a, LL b, LL & x, LL & y, LL & g) {
    if(!b) x = 1, y = 0, g = a;
    else exgcd(b, a % b, y, x, g), y -= x * (a / b);
}

LL inv(LL a, LL p) {
    LL x, y, g;
    exgcd(a, p, x, y, g);
    return g == 1 ? (x % p + p) % p : -1;
}

LL d, res;
LL mul(LL a, LL b, LL p) {
    if(p <= (LL)(1e9)) return 1ll * a * b % p;
    if(p <= (LL)(1e12)) return (((a * (b >> 20) % p) << 20) % p + a * (b & ((1 << 20) - 1))) % p;
    d = (LL)floor(a * (long double) b / p);
    res = (a * b - d * p) % p;
    if(res < 0) res += p;
    return res;
}

static LL c[MAXN], mod[MAXN];

bool excrt(LL & ans, LL & lcm) {
    LL C = c[1] % mod[1], Mod = mod[1], g, x, y, tmp;
    For(i, 2, n) {
        c[i] %= mod[i];
        exgcd(Mod, mod[i], x, y, g);

        if((c[i] - C) % g != 0) return false;
        tmp = mod[i] / g;

        x = mul(x % tmp, ( (c[i] - C) / g ) % tmp, tmp);
        x = (x + tmp) % tmp;

        C += mul(Mod, x, Mod * tmp); 
        Mod *= tmp;
    }
    ans = (C % Mod + Mod) % Mod;
    lcm = Mod;
    return true;
}

int main() {
    multiset<int> :: iterator j;
    int T, g, atk;
    LL mx, ans, lcm;
    bool no_res;

    for(scanf("%d", &T); T --; ) {
        sword.clear();
        scanf("%d%d", &n, &m);
        For(i, 1, n) scanf("%lld", &a[i]);
        For(i, 1, n) scanf("%lld", &p[i]);
        For(i, 1, n) scanf("%d", &gatk[i]);
        For(i, 1, m) {
            scanf("%d", &atk);
            sword.insert(atk);
        }

        mx = 0;
        For(i, 1, n) {
            j = sword.upper_bound(a[i] > 2e9 ? int(2e9) : a[i]);
            if(j != sword.begin()) j --;
            sw[i] = * j;
            sword.erase(j);
            sword.insert(gatk[i]);
            mx = max(mx, (a[i] + sw[i] - 1) / sw[i]);
        }

        no_res = false;
        For(i, 1, n) {
            g = gcd(gcd(sw[i], a[i]), p[i]);
            sw[i] /= g; a[i] /= g; p[i] /= g;
            if(gcd(sw[i], p[i]) != 1) {
                no_res = true;
                break ;
            }
            c[i] = mul(a[i] % p[i], inv(sw[i], p[i]) % p[i], p[i]);
            mod[i] = p[i];
        }
        ans = -1;
        if(!no_res) no_res = !excrt(ans, lcm);
        if(!no_res && ans < mx)
            ans += lcm * ((mx - ans + lcm - 1) / lcm);
        printf("%lld\n", no_res ? -1LL : ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Binary_Heap/article/details/82149212