【LuoguP4774】[NOI2018]屠龙勇士

题目链接

题目描述

自己看去吧

Sol

同步赛上不会multiset....

其实就是一堆同于方程,但是x前面也有系数,即:

a x b   ( m o d   p )

所以先把单个同于方程先用exgcd解出来设为 x 1 ,令 d = g c d ( a , p )
根据我们的求解方法通解为 x 1 + k p d ,这也是个同于方程:
x x 1   ( m o d   p d )

所以先每一个解一下变成这类同余方程,然后就是裸的扩展CRT了

注意当龙的血一开始就大于回复能力的化要保证答案能够把龙的血砍到0以下
不行就不断加合并到最后的模数,也就是所有模数的最小公倍数

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
typedef long long ll;
#define Set(a,b) memset(a,b,sizeof(a))
inline int read()
{
    int x=0;char ch=getchar();int t=1;
    for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=-1;for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);
    return x*t;
}
inline ll readl()
{
    ll x=0;char ch=getchar();int t=1;
    for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=-1;for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);
    return x*t;
}
const int N=1e5+10;
typedef long double ldb;
ll HP[N],p[N],Get[N],atk[N];//打每条巨龙时剑的攻击力可预知
multiset<ll> S;
multiset<ll>::iterator iter;
int n,m;
inline ll Mul(ll a,ll b,ll mod){a%=mod;b%=mod;return (a*b-(ll)((ldb)a*b/mod)*mod+mod)%mod;}
ll gcd(ll a,ll b){return ((b==0)? a:gcd(b,a%b));}
void exgcd(ll a,ll b,ll &x,ll& y)
{
    if(b==0){x=1,y=0;return;}
    exgcd(b,a%b,x,y);register ll tmp=x;x=y;y=tmp-(a/b)*y;
    return;
}
inline bool solve(ll &p,ll &a,ll &b)
{
    register int d=gcd(p,a);
    if(b%d) return 0;
    register ll x,y;exgcd(a,p,x,y);
    p/=d;a/=d;x=(x+p)%p;x=Mul(x,b/d,p);b=x;
    return 1;
}
inline void EXCRT(){
    register ll p1=p[1],a1=atk[1],b1=HP[1],p2,a2,b2;
    if(!solve(p1,a1,b1)) return void(puts("-1"));
    for(register int i=2;i<=n;++i){
        p2=p[i];a2=atk[i];b2=HP[i];
        if(!solve(p2,a2,b2)) return void(puts("-1"));
        if(b2<b1) swap(b1,b2),swap(p1,p2);
        register ll d=gcd(p1,p2),c=b2-b1;
        if(c%d) return void(puts("-1"));
        register ll d1=p1/d,d2=p2/d;c/=d;
        register ll x,y;exgcd(d1,d2,x,y);
        x=(x+d2)%d2;c=Mul(x,c,d2);register ll lcm=d1*p2;
        b1=(b1+Mul(c,p1,lcm))%lcm;p1=lcm;
    }
    for(register int i=1;i<=n;++i){
        if(HP[i]<p[i]) continue;
        while(b1*atk[i]<HP[i]) b1+=p1;
    }
    printf("%lld\n",b1);
    return;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("dragon.in","r",stdin);
    freopen("dragon.out","w",stdout);
#endif
    int T=read();
    while(T--){
        n=read();m=read();S.clear();
        for(register int i=1;i<=n;++i) HP[i]=readl();
        for(register int i=1;i<=n;++i) p[i]=readl();
        for(register int i=1;i<=n;++i) Get[i]=readl();
        for(register int i=1;i<=m;++i) S.insert(readl());
        for(register int i=1;i<=n;++i){
            iter=S.upper_bound(HP[i]);
            if(iter!=S.begin()) --iter;
            atk[i]=*iter;S.erase(iter);
            S.insert(Get[i]);
        }
        EXCRT();
    }
}

猜你喜欢

转载自blog.csdn.net/element_hero/article/details/81781198
今日推荐