White roses, red blood, a pled|

Chillturtle

园龄:4个月粉丝:0关注:0

[NOI 2018] 屠龙勇士 做题笔记

传送门

前言

我是唐诗,考场没开这题。导致看都没看,直接考试策略大失误。其实知道了这题是个扩展中国剩余定理之后就很好做了。

题意

非常奇妙。

小 D 最近在网上发现了一款小游戏。游戏的规则如下:

  • 游戏的目标是按照编号 1n 顺序杀掉 n 条巨龙,每条巨龙拥有一个初始的生命值 ai 。同时每条巨龙拥有恢复能力,当其使用恢复能力时,它的生命值就会每次增加 pi ,直至生命值非负。只有在攻击结束后且当生命值 恰好0 时它才会死去。
  • 游戏开始时玩家拥有 m 把攻击力已知的剑,每次面对巨龙时,玩家只能选择一把剑,当杀死巨龙后这把剑就会消失,但作为奖励,玩家会获得全新的一把剑。

小 D 觉得这款游戏十分无聊,但最快通关的玩家可以获得 ION2018 的参赛资格,于是小 D 决定写一个笨笨的机器人帮她通关这款游戏,她写的机器人遵循以下规则:

  • 每次面对巨龙时,机器人会选择当前拥有的,攻击力不高于巨龙初始生命值中攻击力最大的一把剑作为武器。如果没有这样的剑,则选择 攻击力最低 的一把剑作为武器。
  • 机器人面对每条巨龙,它都会使用上一步中选择的剑攻击巨龙固定的 x 次,使巨龙的生命值减少 x×ATK
  • 之后,巨龙会不断使用恢复能力,每次恢复 pi 生命值。若在使用恢复能力前或某一次恢复后其生命值为 0 ,则巨龙死亡,玩家通过本关。

那么显然机器人的攻击次数是决定能否最快通关这款游戏的关键。小 D 现在得知了每条巨龙的所有属性,她想考考你,你知道应该将机器人的攻击次数 x 设置为多少,才能用最少的攻击次数通关游戏吗?

当然如果无论设置成多少都无法通关游戏,输出 1 即可。

思路

part 1

首先,我们很容易能够知道。其实每一只龙 i 一定有对应的用来砍它的剑。为什么,这里简单证明一下。第一步,注意题目中说的:

每次面对巨龙时,机器人会选择当前拥有的,攻击力不高于巨龙初始生命值中攻击力最大的一把剑作为武器。如果没有这样的剑,则选择 攻击力最低 的一把剑作为武器。

这就说明,每一次选剑的策略是一定的,那么每一只龙就一定有一把对应用来砍它的剑 bi。即使后面加入新的剑也是有同样的。相当于我们可以收先处理出每一只龙所对应的剑。这里的实现必须是 O(nlogn) 的。考虑使用平衡树或者直接使用 multiset显然 multiset 会好写一些。

这一部分的处理代码就长这样(其中 s 就是 multiset):

	for(int i=1;i<=n;i++){
		auto place=s.upper_bound(a[i]);
		if(place!=s.begin()){
			place--;
		}
		b[i]=*place;
		s.erase(place);
		s.insert(t[i]);
		maxn=max(maxn,(a[i]-1)/b[i]+1);
	}

part 2

然后我们进入核心阶段。由于上面我们找到了每一只龙对应的剑 bi 且我们知道 我们要固定攻击 k 次。那么就有我们造成的总伤害为 bi×k。又因为龙的初始生命值为 ai。那么易得满足让这一只龙去世的满足条件的 x 也一定满足下面这个式子:

bi×xai(modqi)

那么多条龙也是一样的,我们就可以列出方程组:

{b1×xa1(modq1)b2×xa2(modq2)......bn×xan(modqn)

part 3

现在已经能看出来,这题明显可以用 ExCrt 求解。但是这里还有个系数 bi。应该怎么办。其实比较好处理。这里笔者参考了 emptysetvvvv 大佬的 博客。这篇文章大致是这样说的:我们先假设我们已经得到了前 i1 个方程的解,记为 res,且假设有 LCM 等于 lcm(p1,p2......pi1)。对于前 i 个方程,我们想得到它们的解就是想找到一个 x 满足下面这式子:

bi×(res+LCM×x)ai(modqi)

为什么?首先我们可以知道 LCM×x+res 为前 i1 的通解。那么上面这个式子就很显然了。

然后,我们把上面那个式子移项。就能发现这个式子其实就等价于:

(bi×LCM)×x+pi×y=aibi×ans

于是直接扩展欧几里得求解。注意计算过程会爆 long long。建议直接使用 __int128

AC code

#include<bits/stdc++.h>
#define int __int128
using namespace std;
namespace WYL{
	const int N=1e5+10;
	multiset<int> s;
	int T,n,m,a[N],b[N],p[N],t[N],maxn=0;
	inline int read(){
		int x=0,f=1;
		char ch=getchar();
		while(ch<'0'||ch>'9'){
			if(ch=='-')
				f=-1;
			ch=getchar();
		}
		while(ch>='0' && ch<='9')
			x=x*10+ch-'0',ch=getchar();
		return x*f;
	}
	inline void Write(int x){
		if(x<0)
			putchar('-'),x=-x;
		if(x>9)
			Write(x/10);
		putchar(x%10+'0');
		return;
	}
	int gsc(int a,int b,int mod){
		int ans=0;
		while(b){
			if(b&1){
				ans=(ans+a)%mod;
			}
			a=(a+a)%mod;
			b/=2;
		}
		return ans;
	}
	void exgcd(int a,int b,int &x,int &y,int &gcd) {
		if(!b){
			x=1;
			y=0;
			gcd=a;	
		}else{
			exgcd(b,a%b,y,x,gcd);
			y-=(a/b)*x;	
		}
		return;
	}
	int solve(){
		int ans=0,lcm=1,x,y,Gcd,yi,er,san;
		for(int i=1;i<=n;i++){
//			yi=gsc(b[i],lcm,p[i]);
			yi=b[i]*lcm%p[i];
//			cout<<"pass1"<<endl;
			er=p[i];
			san=(a[i]-b[i]*ans%p[i]+p[i])%p[i];
//			cout<<"pass2"<<endl;
			exgcd(yi,er,x,y,Gcd);
//			cout<<"pass3"<<endl;
			x=(x%er+er)%er;
			if(san%Gcd){
				return -1;
			}
//			lcm=lcm*(er/Gcd);
			ans=(ans+(san/Gcd)*x%(er/Gcd)*lcm%(lcm*=er/Gcd))%lcm;
//			ans=(ans+gsc(san/Gcd,x,er/Gcd)*lcm%(lcm*er/Gcd))%lcm;
		}
		if(ans<maxn){
			ans=ans+((maxn-ans-1)/lcm+1)*lcm;
		}
		return ans;
	}
	int main(){
		T=read();
		while(T--){
			s.clear();
			n=read();
			m=read();
			maxn=0;
			for(int i=1;i<=n;i++){
				a[i]=read();
			}
			for(int i=1;i<=n;i++){
				p[i]=read();
			}
			for(int i=1;i<=n;i++){
				t[i]=read();
			}
			for(int i=1;i<=m;i++){
				int opt;
				opt=read();
				s.insert(opt);
			}
//			cout<<"pass"<<endl;
			for(int i=1;i<=n;i++){
				auto place=s.upper_bound(a[i]);
				if(place!=s.begin()){
					place--;
				}
				b[i]=*place;
				s.erase(place);
				s.insert(t[i]);
				maxn=max(maxn,(a[i]-1)/b[i]+1);
			}
//			cout<<ExCRT()<<endl;
			Write(solve());
			puts("");
		}
		return 0;
	}
}
signed main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//	freopen("dragon.in","r",stdin);
//	freopen("dragon.out","w",stdout);
	WYL::main();
	return 0;
}

本文作者:Chillturtle

本文链接:https://www.cnblogs.com/OluMel/p/18502096

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Chillturtle  阅读(10)  评论(0编辑  收藏  举报
//雪花飘落效果 html { cursor: url('https://files.cnblogs.com/files/yyyzyyyz/%E6%8C%87%E9%92%88.ico'), auto; }
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起