焦作区域赛--B. Ultraman vs. Aodzilla and Bodzilla--思维

B. Ultraman vs. Aodzilla and Bodzilla

time limit per test

2.0 s

memory limit per test

1024 MB

input

standard input

output

standard output

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 HPAHPA and HPBHPB respectively, and their attack values are ATKAATKA and ATKBATKB 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 ii (i.e. its health point will be decreased by ii) where ii represents that Ultraman has launched iiattacks in total, from the beginning to the present, to these two monsters (and the current attack is the ii-th one). That is to say, during the 11-st second, one of these two monsters will be under an attack of damage 11, during the 22-nd second, one of them, if alive, will be under an attack of damage 22, during the 33-rd second, one of them, if alive, will be under an attack of damage 33, 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 ii-th character in the string is 'A', if the Ultraman chooses to attack Aodzilla during the ii-th second; otherwise, the ii-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 ss and tt, if one string is a prefix of the other, then the one with a shorter length is smaller in lexicographical order. In other cases, ss is smaller than tt in lexicographical order if the first character of ss is smaller than the first character of tt, or in case they are equivalent, the second character of ss is smaller than the second character of tt, etc. The case tt is smaller than ss 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 TT indicating the number of test cases which is up to 105105.

For each test case, the only one line contains four integers HPAHPA, HPBHPB, ATKAATKA and ATKBATKB, where 1≤HPA,HPB,ATKA,ATKB≤1091≤HPA,HPB,ATKA,ATKB≤109.

We guarantee that there are at most 100100 test cases with max{HPA,HPB}>103max{HPA,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.

Example

input

Copy

2
5 15 5 25
5 15 25 5

output

Copy

155 BBBBBA
105 AAABBB

 

预处理出奥特曼攻击值的前缀和,然后分情况讨论:

一、先打A

先算出打死A B一共所用的时间last,pos为打死A所用的时间,然后若if(s[last]-s[pos]>=hb)可以后面直接打死B,否则需要在前面穿插打一下B,打B的是第num[pos]-lb天。

二、先打B

pos为打死B所用的时间,处理出可以保留的时间为locb=s[pos]-hb;,然后找到大于locb的第一个位置,减去1 lb1,若s[lb1]+s[last]-s[pos](差值为bac)大于la,那么可以按ABA的顺序放置。

否则,需要间断性的放A,定义 left=ha-bac,即打死a还需要的时间。如果 if(left-i>i||left==i),则放A,否则放B,最后再放A,使得A可以被消灭掉。----------太难了吧....

#include <algorithm>    //STL通用算法
#include <bitset>     //STL位集容器
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>     //复数类
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>      //STL双端队列容器
#include <exception>    //异常处理类
#include <fstream>
#include <functional>   //STL定义运算函数(代替运算符)
#include <limits>
#include <list>      //STL线性列表容器
#include <map>       //STL 映射容器
#include <iomanip>
#include <ios>      //基本输入/输出支持
#include<iosfwd>     //输入/输出系统使用的前置声明
#include <iostream>
#include <istream>     //基本输入流
#include <ostream>     //基本输出流
#include <queue>      //STL队列容器
#include <set>       //STL 集合容器
#include <sstream>    //基于字符串的流
#include <stack>      //STL堆栈容器    
#include <stdexcept>    //标准异常类
#include <streambuf>   //底层输入/输出支持
#include <string>     //字符串类
#include <utility>     //STL通用模板类
#include <vector>     //STL动态数组容器
#include <cwchar>
#include <cwctype>
#define ll long long
using namespace std;
//priority_queue<int,vector<int>,less<int> >q;
int dx[]= {-1,1,0,0,-1,-1,1,1};
int dy[]= {0,0,-1,1,-1,1,1,-1};
const int maxn = 1000000+66;
const ll mod=1e9+7;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int n,m;
ll s[maxn];
int main()
{
    ll max1=100004;
    for(ll i=1; i<max1; i++)
    {
        s[i]=s[i-1]+1LL*i;
    }
    //前缀和
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll ha,hb,ta,tb;
        scanf("%lld %lld %lld %lld",&ha,&hb,&ta,&tb);
        ll last=lower_bound(s+1,s+max1,ha+hb)-s;
        //能打死两个的天数
        //先打A
        string str;
        string str1;
        ll pos=lower_bound(s+1,s+max1,ha)-s;//打A用的天数
        ll los=s[pos]-ha;//这一天可以打B
        ll s1=1LL*pos*ta+1LL*last*tb;
        if(s[last]-s[pos]>=hb)//可以后面直接放B
        {
            for(ll i=1; i<=pos; i++)
                str+='A';
        }
        else
        {
            for(ll i=1; i<=pos; i++)
            {
                if(i!=los)
                    str+='A';
                else
                    str+='B';
            }
        }
        for(ll i=pos+1; i<=last; i++)
                str+='B';
        //先打B
        pos=lower_bound(s+1,s+max1,hb)-s;
        ll s2=1LL*last*ta+1LL*pos*tb;
        ll locb=s[pos]-hb;//可以空闲的时间和
        ll lb1=upper_bound(s+1,s+max1,locb)-s-1;
        ll bac=s[last]-s[pos];
        if(bac+s[lb1]>=ha)
        {
            for(ll i=1;i<=lb1;i++)
            {
                str1+='A';
            }
            for(ll i=lb1+1;i<=pos;i++)
            {
                str1+='B';
            }
            for(ll i=pos+1;i<=last;i++)
            {
                str1+='A';
            }
        }else
        {
            ll left=ha-bac;//打死a还需要的
            for(ll i=1;i<=pos;i++)
            {
                if(left-i>i||left==i)
                {
                    left-=i;
                    str1+='A';
                }else
                {
                    str1+='B';
                }
            }
            for(ll i=pos+1;i<=last;i++)
            {
                str1+='A';
            }
        }
        if(s1>s2)
        {
            printf("%lld ",s2);
            cout<<str1<<endl;
        }else if(s1<s2)
        {
            printf("%lld ",s1);
            cout<<str<<endl;
        }else if(str<str1)
        {
            printf("%lld ",s1);
            cout<<str<<endl;
        }else
        {
             printf("%lld ",s2);
            cout<<str1<<endl;
        }
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值