[loj2721][NOI2018]屠龙勇士——拓展中国剩余定理 大佬们的博客 Some Links

思路:

如果我们先用multiset把对付没一条龙的攻击力都预处理出来并且设为 t i ,看样子我们是要求这个

{ t 1 x a 1   ( m o d   p 1 ) t 2 x a 2   ( m o d   p 2 ) t n x a n   ( m o d   p n )

但是ExCRT里面并没有前面这个 t ,所以我们先分别把每一个方程解出来,然后每一个方程都可以化为同余式的形式,然后就直接套ExCRT的板子就好啦。值得注意的一点就是这里的并不是求最小正整数解,而是先要用剑把龙的血量砍没,所以最后还要再加上模数直到满足让所有的龙的血量都 0

/*==============================
 * Author : ylsoi
 * Problem : NOI2018 Dragon
 * Algorithm ExCRT
 * Time : 2018.7.23
 * ===========================*/
#include<bits/stdc++.h>

#define REP(i,a,b) for(int i=a;i<=b;++i)
typedef long long ll;

using namespace std;

void File(){
    freopen("loj2721.in","r",stdin);
    freopen("loj2721.out","w",stdout);
}

template<typename T>void read(T &_){
    T __=0,mul=1; char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')mul=-1;
        ch=getchar();
    }
    while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
    _=__*mul;
}

const int maxn=1e5+10;
int T,n,m;
ll a[maxn],p[maxn],t[maxn],lob;
multiset<ll>atk;
multiset<ll>::iterator it;

ll qmul(ll x,ll b,ll mod){
    ll ret=0,mul=1;
    if(b<0)mul=-1,b=-b;
    while(b){
        if(b&1)ret=(ret+x)%mod;
        x=(x+x)%mod;
        b>>=1;
    }
    return ret*mul;
}

ll exgcd(ll aa,ll bb,ll &x,ll &y){
    if(!bb){x=1; y=0; return aa;}
    ll d=exgcd(bb,aa%bb,x,y),tmp=x;
    x=y; y=tmp-aa/bb*y;
    return d;
}

ll get_inv(ll aa,ll bb){
    ll x,y,d=exgcd(aa,-bb,x,y); x/=d;
    return (x%bb+bb)%bb;
}

bool cal(){
    ll x,y,d,dx;
    REP(i,1,n){
        d=exgcd(t[i],-p[i],x,y);
        if(a[i]%d)return false;
        dx=abs(p[i]/d);
        x=qmul(x,a[i]/d,dx);
        x=(x+dx)%dx;
        a[i]=x; p[i]=dx;
    }
    return true;
}

bool work(){
    ll x,y,d,tmp,part1,part2;
    REP(i,2,n){
        d=exgcd(p[i],p[1],x,y);
        if((a[i]-a[1])%d)return false;
        tmp=p[1]; p[1]=p[1]/d*p[i];
        part1=qmul(tmp,(a[i]-a[1])/d,p[1]);
        part2=qmul(part1,get_inv(tmp/d,p[i]/d),p[1]);
        a[1]=(a[1]+part2)%p[1];
        a[1]=(a[1]+p[1])%p[1];
    }
    return true;
}

int main(){
    File();
    read(T);
    while(T--){
        lob=0;
        atk.clear();
        read(n); read(m);
        REP(i,1,n)read(a[i]);
        REP(i,1,n)read(p[i]);
        REP(i,1,n)read(t[i]);
        REP(i,1,m){
            ll u; read(u);
            atk.insert(u);
        }
        REP(i,1,n){
            it=atk.upper_bound(a[i]);
            if(it!=atk.begin())--it;
            atk.insert(t[i]);
            t[i]=*it;
            atk.erase(it);
            lob=max(lob,a[i]/t[i]+(a[i]%t[i] ? 1 : 0));
        }
        if(!cal()){
            puts("-1");
            continue;
        }
        if(!work()){
            puts("-1");
            continue;
        }
        if(a[1]>=lob)printf("%lld\n",a[1]);
        else printf("%lld\n",a[1]+((lob-a[1])/p[1]+((lob-a[1])%p[1] ? 1 : 0))*p[1]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ylsoi/article/details/81170595
今日推荐