zoukankan      html  css  js  c++  java
  • [NOI2018]屠龙勇士

    题目大意:

    n条龙,每条龙有血量a和回血值p,当一条龙血量< 0时,他会不断回血直至≥0。若某一刻龙的血量为0,则该龙死亡。

    你有m把剑,每把剑有攻击力atk,攻击一下造成的伤害等于atk。并且你杀死一条龙后会得到一把新的剑。

    你必须要按顺序杀掉龙,并且每次选择的剑都是atk小于a且最大的那把(如果都不小于a则选atk最小的那一把),杀死后剑消失。

    在打每条龙时,你必须用选择的这把剑攻击K次(对于所有n条龙,K相等),且你必须刚好把它打死。

    问通过的最小K。若不存在,输出-1。

    解题思路:

    首先对于每条龙,攻击它的剑是确定的。我们用multiset维护一下,预处理出对于每条龙要用的剑。

    其次,对于每一组数据,p要么为1,要么大于等于a。

    我们对于p=1的情况,直接特判即可。

    对于p大于等于a的情况,我们相当于得到了n个同余方程(atk imes xequiv apmod p)。

    首先把atk除过去(atk、a、p都先约去公因数,若约去后atk无逆元,则无解),

    然后得到许多形如(xequiv apmod p)的方程,我们要求最小公共解。

    用扩展中国剩余定理即可,即用exgcd每次合并两个同余方程。

    时间复杂度(O(nlog n))。

    C++ Code:

    #include<bits/stdc++.h>
    #define islose(a)if(a)goto die
    using LoveLive=long long;
    const int N=100005;
    template<typename T>
    inline void read(T&d){
    	int c=getchar();d=0;
    	for(;!isdigit(c);c=getchar());
    	for(;isdigit(c);c=getchar())
    	d=(d<<3)+(d<<1)+(c^'0');
    }
    template<typename T>
    T max(const T a,const T b){return a<b?b:a;}
    std::multiset<LoveLive>swd;
    int n,m,g[N];
    LoveLive a[N],p[N],atk[N];
    LoveLive gcd(LoveLive a,LoveLive b){return b?gcd(b,a%b):a;}
    LoveLive exgcd(LoveLive a,LoveLive b,LoveLive&x,LoveLive&y){
    	if(b){
    		auto G=exgcd(b,a%b,y,x);
    		y-=a/b*x;
    		return G;
    	}
    	x=1,y=0;
    	return a;
    }
    inline LoveLive mul(LoveLive a,LoveLive b,LoveLive p){
        auto ans=a*b-(LoveLive)((long double)a/p*b+1e-9)*p;
        return(ans+p)%p;
    }
    LoveLive crt(){
    	LoveLive A=a[1],P=p[1],x,y,d;
    	for(int i=2;i<=n;++i){
    		d=exgcd(P,p[i],x,y);
    		if((A-a[i])%d)return -1;
            A-=P*mul((A-a[i])/d,x,(p[i]/d));
            P=P/d*p[i];
            A=(A+P)%P;
    	}
    	return(A+P)%P;
    }
    int main(){
    	int T;
    	for(read(T);T--;){
    		swd.clear();
    		read(n),read(m);
    		bool p_1=true;
    		for(int i=1;i<=n;++i)read(a[i]);
    		for(int i=1;i<=n;++i)read(p[i]),p_1=p_1&&p[i]==1;
    		for(int i=1;i<=n;++i)read(g[i]);
    		while(m--){
    			int p;
    			read(p);
    			swd.insert(p);
    		}
    		for(int i=1;i<=n;++i){
    			auto it=swd.upper_bound(a[i]);
    			if(it!=swd.begin())--it;
    			atk[i]=*it;
    			swd.erase(it);
    			swd.insert(g[i]);
    		}
    		LoveLive ans=0,aans;
    		for(int i=1;i<=n;++i)
    		ans=max(ans,(a[i]-1)/atk[i]+1);
    		if(p_1){
    			printf("%lld
    ",ans);
    			continue;
    		}
    		for(int i=1;i<=n;++i){
    			auto G=gcd(p[i],atk[i]);
    			islose(a[i]%G);
    			p[i]/=G,atk[i]/=G,a[i]/=G;
    			LoveLive x,y;
    			exgcd(atk[i],p[i],x,y);
    			x=(x%p[i]+p[i])%p[i];
    			a[i]=mul(a[i],x,p[i]);
    		}
    		aans=crt();
    		islose(aans==-1);
    		if(aans<ans){
    			int lcm=1;
    			for(int i=1;i<=n;++i)lcm=lcm/gcd(lcm,p[i])*p[i];
    			if(!aans)aans=lcm;else
    			aans+=(ans-aans+lcm-1)/lcm*lcm;
    		}
    		printf("%lld
    ",aans);
    		continue;
    		die:puts("-1");
    	}
    	return 0;
    }
    
  • 相关阅读:
    XOR加密作业
    2019-2020-1 20191312《信息安全专业导论》第六周学习总结
    欧几里得算法及其伪代码
    2019-2020-1 20191312《信息安全专业导论》第五周学习总结
    2019-2020-1 20191312《信息安全专业导论》第四周学习总结
    寻找你的黑客偶像作业
    2019-2020-1 20191312 《信息安全专业导论》第三周学习总结
    罗马数字转化为阿拉伯数字
    IEEE754 浮点数
    2019-2020-2 网络对抗技术 20175211 Exp6 MFS基础应用
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9350077.html
Copyright © 2011-2022 走看看