题目翻译
在某款电脑游戏里,角色初始生命 $hc$,初始攻击 $dc$。怪物初始生命 $hm$,初始攻击 $dm$。
而你有 $k$ 次机会,将攻击力永久提升 $w$ 或者将生命永久提升 $a$ 。
每一轮,角色攻击怪物,怪物掉 $dc$ 生命。怪物攻击角色,角色掉 $dm$ 生命。
问若干轮以后,角色能否击杀怪物并且角色存活。
击杀怪物定义为:怪物生命 $\ngtr 0$。
角色存活定义为:角色生命 $>0$。
题目思路(不完整)
我们枚举这 $k$ 次机会,分别是加攻击还是加生命。然后判断角色增加这些属性后,能否击败怪物。
而且每一轮的攻击,如果角色击败了怪物,怪物不会攻击角色。也就是说,怪物可以少打一轮伤害。
题目代码(不完整)
void solve()
{
long long hc,dc,hm,dm,k,w,a;
cin>>hc>>dc>>hm>>dm>>k>>w>>a;//输入属性
for(long long i=0;i<=k;i++)
{
long long x=i,y=k-i;//枚举加攻击或加生命
long long rnd=ceil(hm*1.0/(dc+x*w));//用怪物血量除以角色攻击得到轮数
if(dm*(rnd-1)<hc+a*y)//如果怪物打出的伤害比角色生命少
{
puts("YES");//可以通关
return;
}
}
puts("NO");
}
但是,看似没问题,实则会在第 $13$ 个数据点错误。
让我们导出看一下。
Input
1
1 1
1000000000000000 1000000000
200000 1 10000000000
Output
YES
Answer
NO
我们进行调试,分别输出每个循环的结果。
1
1 1
1000000000000000 1000000000
200000 1 10000000000
加攻击机会数:0 加生命机会数:200000 总轮数:1000000000000000 怪物打出伤害:2003764204206896640 角色生命:2000000000000001
加攻击机会数:1 加生命机会数:199999 总轮数:500000000000000 怪物打出伤害:1001882101603448320 角色生命:1999990000000001
加攻击机会数:2 加生命机会数:199998 总轮数:333333333333334 怪物打出伤害:667921401402298880 角色生命:1999980000000001
加攻击机会数:3 加生命机会数:199997 总轮数:250000000000000 怪物打出伤害:-8722430986553051648 角色生命:1999970000000001
YES
答案竟然爆 long long
了。
那么我们没办法了吗?错!__int128
了解一下?
我们给总轮数换上 __int128
即可。
总结
思想是对于加攻击还是加生命都考虑一下,找出每种可能。
注意数据范围。
代码不给了,就是改个 __int128
的事。