Ultraman vs. Aodzilla and Bodzilla
Problem Description
Six months ago our hero, formerly known as Huriyyah, was beating all monsters in the land. Now he changed his name to Ultraman and left his beloved land. He is ready to take on a new challenge.
In a remote land, local citizens are suffering from the harassment of two powerful and horrible monsters: Aodzilla and Bodzilla. They eat small children who go out alone and even kill innocent persons. The apprehension of being attacked has overwhelmed people for several decades.
For the good of these unfortunate citizens, Ultraman sets out for the forest which is the main lair of Aodzilla and Bodzilla. In the forest, he faces these two fierce and cruel monsters and fights with them. The health points of Aodzilla and Bodzilla are H P A HP_A HPA and H P B HP_B HPB respectively, and their attack values are A T K A ATK_A ATKA and A T K B ATK_B ATKB respectively.
They fight in a cave through turn-based battles. During each second, the Ultraman will be attacked by monsters at first, and the damage is the sum of attack values of all alive monsters. Then he will select exactly one monster which is still alive and attack it. The selected monster will suffer a damage of value i i i (i.e. its health point will be decreased by i i i) where i i i represents that Ultraman has launched i i i attacks in total, from the beginning to the present, to these two monsters (and the current attack is the i i i-th one). That is to say, during the 1 1 1-st second, one of these two monsters will be under an attack of damage 1, during the 2-nd second, one of them, if alive, will be under an attack of damage 2, during the 3-rd second, one of them, if alive, will be under an attack of damage 3, and so on. If at some time, the health point of a monster is less than or equal to zero, it will die immediately. The Ultraman will win if both monsters have been killed.
Now, you are asked to develop a strategy to minimize the total damage Ultraman should suffer before he wins the battle. A strategy can be described as a string whose length is the total time that the battle will last. The i-th character in the string is ‘A’, if the Ultraman chooses to attack Aodzilla during the i-th second; otherwise, the i-th character is ‘B’, which means Bodzilla will be the target during that second. You are also asked to find the optimal strategy whose string description is the smallest in lexicographical order among all possible optimal strategies.
For two distinct strings s and t, if one string is a prefix of the other, then the one with a shorter length is smaller in lexicographical order. In other cases, s is smaller than t in lexicographical order if the first character of s is smaller than the first character of t, or in case they are equivalent, the second character of s is smaller than the second character of t, etc. The case t is smaller than s in lexicographical order is defined similarly as the former case.
Input
The input contains several test cases, and the first line contains a positive integer T T T indicating the number of test cases which is up to 1 0 5 10^5 105.
For each test case, the only one line contains four integers H P A , H P B , A T K A HP_A, HP_B, ATK_A HPA,HPB,ATKA and A T K B ATK_B ATKB, where 1 ≤ H P A , H P B , A T K A , A T K B ≤ 1 0 9 1≤HP_A,HP_B,ATK_A,ATK_B≤10^9 1≤HPA,HPB,ATKA,ATKB≤109.
We guarantee that there are at most 100 100 100 test cases with m a x H P A , H P B > 1 0 3 max{HP_A,HP_B}>10^3 maxHPA,HPB>103.
Output
For each test case, output a line containing an integer indicating the minimal total damage Ultraman should suffer, and a string describing the optimal strategy such that the string description is the smallest in lexicographical order among all possible optimal strategies. You should output exactly one whitespace between the number and the string.
Sample Input
2
5 15 5 25
5 15 25 5
Sample Output
155 BBBBBA
105 AAABBB
题意
有两只怪兽A,B,怪兽A的血量为
H
P
A
HP_A
HPA,攻击力为
A
T
K
A
ATK_A
ATKA;怪兽B的血量为
H
P
B
HP_B
HPB,攻击力为
A
T
K
B
ATK_B
ATKB。你每次可以选择一只活着的怪兽攻击 ,第i回合可以造成i点伤害,每个回合你攻击前,活着的怪兽会先攻击你,造成与攻击力等额伤害。当怪物血量小于等于0,则怪物死亡,不可再被攻击或造成伤害。
求你击败两支怪物的同时,最小化自己受到的伤害。同时给出字典序最小的攻击序列。
思路
可以看出一直怪兽越早被击败越好,那样可以保证自己受到的伤害最小。 分类讨论是先击败A,还是先击败B。
设数组 a a a, a [ i ] = 1 + 2 + 3... + i a[i]=1+2+3...+i a[i]=1+2+3...+i.
先击败A:
设连续攻击到pos1回合,A会被击败,之后再连续攻击B到pos3回合,B会被击败。暂时将攻击方案定为此方案。
若
a
[
p
o
s
3
]
−
a
[
p
o
s
2
]
≥
H
P
B
a[pos3]-a[pos2]\ge HP_B
a[pos3]−a[pos2]≥HPB,则代表攻击
[
p
o
s
1
+
1
,
p
o
s
3
]
[pos1+1,pos3]
[pos1+1,pos3]回合造成的伤害足以击败B,使用暂定方案即可。
若
a
[
p
o
s
3
]
−
a
[
p
o
s
2
]
≤
H
P
B
a[pos3]-a[pos2]\le HP_B
a[pos3]−a[pos2]≤HPB,则代表后面几次的伤害不足以击败B,则考虑将部分攻击A的回合转移给B。因为前pos1个回合攻击A溢出的伤害肯定是<pos1的,且要求攻击序列字典序最小,则保留正好击败A的方案即可,将尽量靠后的一次攻击调整为攻击B(A,B的死亡时间并未改变,所以受到的伤害也未变)。即将第a[pos1]-HPA回合的攻击调整为攻击B即可。
先击败B:
设连续攻击到pos2回合,B会被击败,之后再连续攻击A到pos3回合,A会被击败。暂时将攻击方案定为此方案。
在攻击B时,溢出的伤害
x
=
a
[
p
o
s
2
]
−
H
P
B
x = a[pos2]-HP_B
x=a[pos2]−HPB,为了使攻击序列字典序最小,则将前pos(满足
a
[
p
o
s
]
≤
x
a[pos]\le x
a[pos]≤x的最大值)次攻击调整为A。
若
a
[
p
o
s
]
+
a
[
p
o
s
3
]
−
a
[
p
o
s
2
]
≥
H
P
A
a[pos]+a[pos3]-a[pos2] \ge HP_A
a[pos]+a[pos3]−a[pos2]≥HPA,则按照上述策略将前POS次攻击调整为A即可。
若
a
[
p
o
s
]
+
a
[
p
o
s
3
]
−
a
[
p
o
s
2
]
<
H
P
A
a[pos]+a[pos3]-a[pos2] < HP_A
a[pos]+a[pos3]−a[pos2]<HPA,则在前pos次攻击中,还需要调整,对A造成
y
=
H
P
A
−
(
a
[
p
o
s
3
]
−
a
[
p
o
s
2
]
)
y = HP_A-(a[pos3]-a[pos2])
y=HPA−(a[pos3]−a[pos2])点伤害。字典序最小,则要从小到大考虑第i回合,若
k
≥
2
∗
i
+
1
∣
∣
k
=
=
i
k \ge 2*i+1 || k==i
k≥2∗i+1∣∣k==i,则当前回合调整为攻击A,并且k-=i。
(
k
≥
2
∗
i
+
1
k \ge 2*i+1
k≥2∗i+1是因为若
k
<
2
∗
i
+
1
k<2*i+1
k<2∗i+1,当前回合若攻击A,则(k=k-i)<i,后面每次攻击减少的血量都是大于i的,则k无法为0)
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#include<set>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-6
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 1100100;
const int mod = 998244353;
LL num, a[maxn];
char str1[maxn], str2[maxn];
int main()
{
int t, hp1, hp2, at1, at2, i, j, k, n, m;
LL mi, num;
n = 1100005;
for(i=1;i<=n;i++)
a[i] = a[i-1]+i;
scanf("%d", &t);
while(t--)
{
scanf("%d %d %d %d", &hp1, &hp2, &at1, &at2);
int pos1 = lower_bound(a, a+n, hp1)-a;
int pos2 = lower_bound(a, a+n, hp2)-a;
int pos3 = lower_bound(a, a+n, hp1+hp2)-a;
str1[pos3+1] = str2[pos3+1] = 0;
for(i=1;i<=pos1;i++)str1[i] = 'A';
for(i=pos1+1;i<=pos3;i++)str1[i]='B';
mi = 1LL*at1*pos1+1LL*at2*pos3;
if(a[pos3]-a[pos1] < hp2)
str1[a[pos1]-hp1] = 'B';
num = 1LL*pos2*at2+1LL*pos3*at1;
for(i=1;i<=pos2;i++)str2[i] = 'B';
for(i=pos2+1;i<=pos3;i++)str2[i] = 'A';
int pos = upper_bound(a+1, a+101000, a[pos2]-hp2)-a-1;
if(a[pos]+a[pos3]-a[pos2] >= hp1){
for(i=1;i<=pos;i++)str2[i] = 'A';
}else{
k = hp1-(a[pos3]-a[pos2]);
for(i=1;i<=pos2;i++)
if(k-i>i || k == i){
k -= i;
str2[i] = 'A';
}else str2[i] = 'B';
}
if(mi < num)printf("%lld %s\n", mi, str1+1);
else if(mi > num)printf("%lld %s\n", num, str2+1);
else if(strcmp(str1+1, str2+1)<=0)printf("%lld %s\n", mi, str1+1);
else printf("%lld %s\n", num, str2+1);
}
return 0;
}