题解 | #打怪#
打怪(hard)
https://ac.nowcoder.com/acm/contest/59248/C
打怪
当游戏结束时必须满足以下两个条件之一:
- 攻击力等于对方的血量
- 防御力等于对方的攻击力
当攻击力为a时,防御力为b时。获得一个金币的代价为
对于任何一种情况来说都可以归纳成以下表格情况情况: ()
扣血量 | 敌方攻击次数 |
---|---|
... | ... |
我们可以观察到升级防御时后,将会出现两次。 之后将相同攻击次数的情况划分成同一类后获得不同的数,对于某个攻击次数为、个数为的情况,贪心考虑后得到两种代价,每次选择代价小的那个,然后累计到ans上。
- 为扣血量x的最后一个:
- 不是最后一个:
当攻击力等于对方的血量时, 防御力等于对方的攻击力,
对于中间的任何情况来说,结束的代价为。 当时退出循环即可:
void slove() {
ll ad = read(), hp = read();
hp--;
ll res = hp * (1 + ad) * ad / 2, ans = 0;
ll x = ad;
for (ll l = 1, r, y; l <= hp && x > 0; l = r + 1) {
y = hp / l, r = hp / y;
ll len = r - l + 1;
// 总代价
res = min(res, y * x * (1 + x) / 2 + ans);
if (x - len <= 0) {
ans += (2 * x - 1) * len * y;
x--;
} else ans += x * len * y;
}
print(min(res, ans));
}