本题解借鉴了某大佬的博客,由于那篇博客里有点小错误,因此我这里重写一篇,希望大家在看到我的博客的同时也关注一下那位大佬。
大佬博客地址
题目链接
题解思路:很显然,要使奥特曼受到的伤害最小,肯定要先杀死一只怪兽,所以我们就分类讨论先杀A还是先杀B。
//不少人可能会说比较一下A,B的攻击力,先杀攻击力高的一定会更优。但这是错误的,比如一个100血10攻的怪和一只3血9攻的怪,显然是要先杀3血9攻的那只怪。
因此,我们就分类先杀A还是先杀B,然后比较两者的耗费和字典序,取最小即可。
首先处理一个前缀和的数组pri[i]表示1到i时刻的伤害总和。
我们先算出最快打死A的回合:u1=lower_bound(pri+1,pri+100000,a.H)-pri
打死两个怪的最快时间:u2=lower_bound(pri+1,pri+100000,a.H+b.H)-pri
(1)哪怕不分A溢出的伤害,剩下的伤害也足以在u2-u1回合内打死B
这样肯定是1-u1是A,u1+1到u2是B字典序最小。
(2)pri[u2]-pri[u1]
在这种情况下,A溢出的伤害必然要打到B上,那应该在那一次打呢?自然是尽可能靠后,B越靠后字典序越小。
算出最快打死B的回合:u1=lower_bound(pri+1,pri+100000,b.H)-pri
先杀B分伤害给A的情况处理起来就比较麻烦,因为要使A尽可能靠前,这里最好的情况就是在伤害值<=B溢出伤害时前面能插入一段连续的A,然后这段的伤害+pri[u2]-pri[u1]>=a.H,这样能保证B先死且A尽可能地靠前。可是如果不行呢,我们就只能把前面连续的A拆出来,往后移,让对A的伤害值变大,这样才能打死两只怪兽。
(1)一段A的前缀+pri[u2]-pri[u1]>=a.H
(2)在上述情况打不死的情况下,定义left=a.H-(pri[u2]-pri[u1]) (前面那部分所需要造成的伤害)。在1-u1的回合,当left>=2*i+1 || left==i 的时候插入A,left -= i,否则插入B,剩下的全是A。
#include
using namespace std;
#define maxn 300005
#define ll long long
const int mod = 1e9 + 7;
int T;
ll pri[maxn];
struct node{
ll H,K;
}a,b;
void init(){
for(int i=1;i<=1e5;i++)
pri[i]=pri[i-1]+i;
}
int main()
{
init();
scanf("%d",&T);
while(T--){
ll suma=0,sumb=0;
string ansa,ansb;
scanf("%lld %lld %lld %lld",&a.H,&b.H,&a.K,&b.K);
//A先死-
int u1=lower_bound(pri+1,pri+100000,a.H)-pri;
int u2=lower_bound(pri+1,pri+100000,b.H+a.H)-pri;
ll left=pri[u1]-a.H;
suma=a.K*u1+b.K*u2;
if(pri[u2]-pri[u1]>=b.H){
for(int i=1;i<=u1;i++)
ansa+='A';
for(int i=u1+1;i<=u2;i++)
ansa+='B';
}
else{
for(int i=1;i<=u1;i++){
if(i==left)ansa+='B';
else ansa+='A';
}
for(int i=u1+1;i<=u2;i++)
ansa+='B';
}
//B先死
u1=lower_bound(pri+1,pri+100000,b.H)-pri;
u2=lower_bound(pri+1,pri+100000,a.H+b.H)-pri;
sumb=b.K*u1+a.K*u2;
left=pri[u1]-b.H;
int pos=upper_bound(pri+1,pri+100000,left)-pri-1;
if(pri[pos]+pri[u2]-pri[u1]>=a.H){
for(int i=1;i<=pos;i++)
ansb+='A';
for(int i=pos+1;i<=u1;i++)
ansb+='B';
for(int i=u1+1;i<=u2;i++)
ansb+='A';
}
else{
left=a.H-(pri[u2]-pri[u1]);
for(int i=1;i<=u1;i++){
if(left>=2*i+1||left==i){
left-=i;
ansb+='A';
}
else ansb+='B';
}
for(int i=u1+1;i<=u2;i++)
ansb+='A';
}
if(suma<sumb)cout<<suma<<" "<<ansa<<"\n";
else if(sumb<suma)cout<<sumb<<" "<<ansb<<"\n";
else{
if(ansa<ansb)cout<<suma<<" "<<ansa<<"\n";
else cout<<sumb<<" "<<ansb<<"\n";
}
}
return 0;
}