[NOI2018] 屠龙勇士 扩展中国剩余定理 ExCRT

N O I n 天后我才改完D2T1, 是真的菜啊我 q w q .
步入正题 这道题由于杀龙顺序是一定的 首先我们可以用一个 m u l t i s e t 来维护每一条龙被攻击力为多少的剑所杀 处理出杀每条龙的剑之后 我们发现这就是很多个 k x a i ( m o d p i ) 这样的方程 我们可以通过 e x g c d 把它转换成 x a i ( m o d b i ) h a p p y 使 E x c r t
如果你还不会 e x c r t 可以看这篇博客
对了 对于这个题我们应该采用数据分治
我们的做法都是基于 a i <= p i 的条件下
观察数据表可以发现 不满足 a i <= p i 的点可以直接算
那么大力特判掉这种情况就可以过掉此题啦

c o d e

#include<bits/stdc++.h>
#define For(i, a, b) for(register int i = a; i <= b; ++ i)

using namespace std;
typedef long long ll;

const int maxn = 1e5 + 10;
ll a[maxn], p[maxn], K[maxn], M[maxn], X[maxn], B[maxn];
ll n, m, nowx, nowb = 1, minn;
multiset<ll>::iterator it;
multiset<ll> Tree;

ll mul(ll a, ll b, ll mod) {
    ll res = 0, f = 1;
    if(b < 0) b *= (f = -1);
    while(b) {
        if(b & 1)
            (res += a) %= mod;
        b >>= 1, (a <<= 1) %= mod;
    }
    return res * f;
}

ll ex_gcd(ll a, ll &x, ll b, ll &y) {
    if(!b) {
        x = 1, y = 0;
        return a;
    }
    ll gcd = ex_gcd(b, x, a % b, y);
    ll xx = y, yy = x - a / b * y;
    x = xx, y = yy;
    return gcd;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("4774.in", "r", stdin);
    freopen("4774.out", "w", stdout);
#endif
    ll T, x, y;
    for(scanf("%lld", &T); T -- ; ) {
        bool flag = 0, fuck = 0;
        Tree.clear();
        nowx = 0, nowb = 1, minn = 0;
        scanf("%lld%lld", &n, &m);
        For(i, 1, n) scanf("%lld", &a[i]);
        For(i, 1, n) {
            scanf("%lld", &p[i]);
            if(p[i] != 1)
                fuck = 1;
        }
        For(i, 1, n) scanf("%lld", &M[i]);
        For(i, 1, m) {
            scanf("%lld", &x);
            Tree.insert(x);
        }
        For(i, 1, n) {
            it = Tree.upper_bound(a[i]);
            if(it != Tree.begin()) -- it;
            K[i] = *it, Tree.erase(it);
            ll gcd = ex_gcd(K[i], X[i], p[i], y);
            if(a[i] % gcd != 0) {
                flag = 1; 
                break;
            }
            minn = max(minn, ll(ceil(1.0 * a[i] / K[i])));
            B[i] = p[i] / gcd;
            X[i] = mul(X[i], a[i] / gcd, B[i]);
            X[i] = (X[i] + B[i]) % B[i];
            Tree.insert(M[i]);
        }
        if(!fuck) {
            printf("%lld\n", minn);
            continue;
        }
        if(flag) {
            puts("-1");
            continue;
        }
        For(i, 1, n) {
            ll gcd = ex_gcd(nowb, x, B[i], y);
            if((X[i] - nowx) % gcd != 0) {  
                flag = 1; 
                break;
            }
            x = mul(x, (X[i] - nowx) / gcd, B[i] / gcd);
            x = (x + B[i] / gcd) % (B[i] / gcd);
            nowx = nowb * x + nowx;
            nowb = (nowb / gcd * B[i]);
            nowx %= nowb;
        }
        if(flag) {
            puts("-1");
            continue;
        }
        printf("%lld\n", nowx);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lunch__/article/details/81200560