题目

小爱和小艾两人组队打一只怪兽。一开始怪兽有 n 点生命值,当 n 变成 0 或更低时,怪兽就被消灭了。他们两人是同时开始攻击的,小爱每分钟可以攻击 aa 下,小艾每分钟可以攻击 b 下。若 a=2b=4,则小爱发出攻击的时刻为

0.5, 1, 1.5, 2, 2.5, 

小艾发出攻击的时刻为

0.25, 0.5, 0.75, 1, 1.25, 1.5, 

攻击分两种类型,普通攻击每次对怪兽造成 1 点伤害。若在某时刻,小爱和小艾恰好一同发出攻击,称为爆击爆击将对怪兽造成成倍的伤害,共计 (1+1)×2=4 点伤害。

一旦攻击开始,就不会中断,直到怪兽被消灭为止,请问,对怪兽造成最后一点伤害的是哪一位玩家?如果最后一击是两人同时造成的,输出 C(Combo的意思)。

输入格式

第一行:一个正整数表示 n
第二行:两个正整数表示 ab

输出格式

  • 若是小爱发出了最后一击,输出 A
  • 若是小艾发出了最后一击,输出 B
  • 若是两人的爆击为最后一击,输出 C

限制:

  • 1n2×107
  • 1a,b40000

算法分析

  1. 把每分钟分成 a×b 份,这样是为了让他们攻击的点都在整数上
    那么小爱攻击 a 下,则攻击间隔是 b 时间
    小艾攻击 b 下,则攻击间隔是 a 时间

暴击的性质:一定是 a 的倍数,也一定是 b 的倍数,公倍数
公倍数为最小公倍数的倍数

所以暴击点就是 lcm(a,b) 的倍数

  1. lcm(a,b) 是一个循环,可以计算出攻击的伤害,用生命值 % 伤害,最后看剩下的生命。
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, a, b;
cin >> n >> a >> b;
int l = lcm(a, b);
int dm = l/b + l/a + 2;
n %= dm;
if (n == 0 or n == dm-1 or n == dm-2 or n == dm-3) {
puts("C");
return 0;
}
int nowa = b; // a 第一次攻击在 b 时刻
int nowb = a; // b 第一次攻击在 a 时刻
for (int i = 1; i <= n; ++i) {
if (nowa < nowb) {
if (i == n) {
puts("A");
}
nowa += b;
}
else {
if (i == n) {
puts("B");
}
nowb += a;
}
}
return 0;
}