Luogu P4774 / LOJ2721 【[NOI2018]屠龙勇士】

真是个简单坑题...++

前置:

exgcdexCRTSTL-multiset

读完题不难发现,攻击每条龙用的剑都是可以确定的,可以用multiset求。攻击最少显然应该对于每一条龙都操作一次,即攻击\(x\)次。设对于第\(i\)条龙,攻击时使用的剑的攻击力为\(us_i\),生命值为\(hp_i\),恢复能力为\(rh_i\),则\(us_ix\equiv hp_i\pmod{rh_i}\)。然后仔细阅读数据范围和提示,会发现存在\(hp_i>rh_i\)的情况,此时\(rh_i=1\),也即求\(\max\{\Large\lceil\frac{hp_i}{us_i}\rceil\normalsize\}\)。对于\(hp_i\leq rh_i\)的情况,可以直接用exCRT求答案。而exCRT适用于\(x\)系数为\(1\)的情况,此处需要用exgcd求出\(\large\frac{hp_i}{us_i}\normalsize\pmod{rh_i}\),转化为\(x\equiv a_i\pmod{p_i}\)形式。剩下的就只需要exCRT板子了。可能会爆long long的乘法转用龟速乘就好了。

#include<bits/stdc++.h>

using namespace std;

void qread(long long &xx){
	xx=0;int ch=getchar();
	while(ch<'0'||ch>'9'){
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		xx=xx*10+ch-'0';
		ch=getchar();
	}
}

const int N=1e5+5;

long long t,n,m,ans,lcm,mx;

long long hp[N],rh[N],aw[N],st[N],us[N],a[N],p[N];

multiset<long long>ms;

long long mul(long long u,long long v,long long MOD){
	long long rep=0;
	while(v>0){
		if(v&1){
			rep=(rep+u)%MOD;
		}
		u=(u+u)%MOD;
		v>>=1;
	}
	return rep;
}

long long exgcd(long long u,long long v,long long &x,long long &y){
	if(v==0){
		x=1;y=0;
		return u;
	}
	long long _w=exgcd(v,u%v,y,x);
	y-=u/v*x;
	return _w;
}

long long x,y;

void excrt(){
	ans=a[1];lcm=p[1];
	for(int i=2;i<=n;i++){
		long long rep=(((a[i]-ans)%p[i])+p[i])%p[i];
		long long g=exgcd(lcm,p[i],x,y);
		long long pg=p[i]/g;
		if(rep%g){
			ans=-1;
			return;
		}
		x=mul(x,rep/g,pg);
		ans+=lcm*x;
		lcm=lcm*pg;
		ans=((ans%lcm)+lcm)%lcm;
	}
	ans=((ans%lcm)+lcm)%lcm;
}

bool check(){
	for(int i=1;i<=n;i++){
		if(hp[i]>rh[i]){
			return 0;
		}
	}
	return 1;
}

int main(){
	qread(t);
	while(t--){
		ans=mx=0;
		qread(n);qread(m);
		for(int i=1;i<=n;i++){
			qread(hp[i]);
		}
		for(int i=1;i<=n;i++){
			qread(rh[i]);
		}
		for(int i=1;i<=n;i++){
			qread(aw[i]);
		}
		for(int i=1;i<=m;i++){
			qread(st[i]);
		}
		ms.clear();
		for(int i=1;i<=m;i++){
			ms.insert(st[i]);
		}
		multiset<long long>::iterator ite;
		for(int i=1;i<=n;i++){
			ite=ms.upper_bound(hp[i]);
			if(ite!=ms.begin()){
				--ite;
			}
			us[i]=*ite;
			ms.erase(ite);
			ms.insert(aw[i]);
		}
		for(int i=1;i<=n;i++){
			mx=max(mx,(long long)ceil((double)hp[i]/(double)us[i]));
			long long g=exgcd(us[i],rh[i],x,y);
			p[i]=rh[i]/g;
			if(hp[i]%g){
				ans=-1;
				break;
			}
			x=((x%p[i])+p[i])%p[i];
			a[i]=mul(hp[i]/g,x,p[i]);
		}
		if(!ans){
			if(check()){
				excrt();
			}
			else{
				for(int i=1;i<=n;i++){
					ans=max(ans,(long long)ceil((double)hp[i]/(double)us[i]));
				}
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2019-04-19 20:54  __BLUESKY007  阅读(299)  评论(1编辑  收藏  举报