#P9381. [THUPC 2023 决赛] 那些脑海里最珍贵的
[THUPC 2023 决赛] 那些脑海里最珍贵的
Background
E.Space: The setting is weird. Do not ask why. If you ask, the answer is “see the attachment”.
Nonsense that nobody understood
Do you still remember
A wall full of youth
That stubbornness of practicing so hard
Shallow scars
Courage is our wings
— Angela Zhang, “Do You Still Remember”
Problem Description
The world setting of the story is roughly like this. People in this world are divided into three types, and are directly named Weak, Average, and Strong based on some characteristic. You may think of this as a classification of races or professions.
A turn-based battle happened between two teams. You know what both sides did, and now you are asked to restore all details.
Below are some technical details of this problem.
[Characters]
A character has the following attributes: “race”, “level”, “max HP”, “base attack index”, “base defense index”, “active skill level”, and “passive skill level”. Among them, “max HP”, “base attack index”, and “base defense index” are fully determined by “race” and “level”. However, for input convenience, all information is given in this problem. In battle, each character has an “HP”. At the start of the battle, “HP” equals “max HP”. When “HP” is less than or equal to , the character “falls”. For the same “race”, “max HP”, “base attack index”, and “base defense index” roughly grow exponentially with “level”. Each character holds a “weapon”. Details of “weapons” are given in the next section.
[Weapons]
A “weapon” has only two attributes: “weapon type” and “weapon attack”. All “weapons” have two ways to attack: “basic attack” and “special attack”. Initiating an “attack” means using either of these two ways. The effect of “basic attack” is independent of “weapon type”, but different “weapon types” have different “special attack” effects. There are three weapon types: “B”, “G”, and “M”.
[Battlefield and Teams]
Each side has at most members, standing in one line. From west to east, their IDs are (if there are fewer than members, delete the larger IDs). For convenience, call the two teams “South Team” and “North Team”.
[Turns]
In each “turn”, only one person can “act”. Odd-numbered turns are acted by a member of “South Team”, and even-numbered turns are acted by a member of “North Team”. In the first and second turns, the acting person is the not-fallen member with the smallest ID in the team. In later turns, if there is no not-fallen member in the team whose ID is larger than the previous acting person of this team, then the not-fallen member with the smallest ID in the team acts. Otherwise, among members with ID larger than the team’s previous actor, the not-fallen one with the smallest such ID acts. If all members of a team have fallen, the other team is judged to “win”.
[Actions]
There are three types of “actions”. The acting person in the current “turn” must choose exactly one of the three.
- “Basic attack”.
- “Special attack”.
- “Active skill”.
The effects of these actions will be described later. “Special attack” and “active skill” have usage limits, but in this problem, all actions are guaranteed to be legal, so you do not need to consider these limits.
[Damage Calculation]
“Damage” means the reduction of “HP” caused by “basic attack” or “special attack”.
The amount of “damage” (i.e. the HP reduction) is determined by “attack intensity” and the “defense index” of the damaged person.
A person’s “defense index” equals the person’s “base defense index” multiplied by the team’s “defense bonus”.
Specifically, if a person receives “damage” with “attack intensity” , then their “HP” decreases by , where $y=\left\lfloor \dfrac{x}{\text{defense index}} \right\rfloor$.
“Attack intensity” equals “base attack intensity” multiplied by the attacker’s “skill multiplier”, multiplied by the team’s “attack bonus”, multiplied by the “race counter multiplier”, multiplied by the “position multiplier”. These concepts will be introduced later.
[Basic Attack]
Choose an enemy member who has not “fallen” as the “target”. The “target” receives “damage” whose “base attack intensity” is (the attacker’s “base attack index”) multiplied by (the “weapon attack”).
[Special Attack]
Choose an enemy member who has not “fallen” as the “target”.
There are three weapon types, and their “special attack” effects are:
- “B”: The “target” receives “damage” whose “base attack intensity” is (the attacker’s “base attack index”) (the “weapon attack”) .
- “G”: The “target”, and also the nearest not-fallen member on the west side of the “target” (if it exists) and the nearest not-fallen member on the east side of the “target” (if it exists), all receive “damage” whose “base attack intensity” is (the attacker’s “base attack index”) (the “weapon attack”) . Here divided by the number of people who will receive “damage”. Damage is calculated in the order: “target”, west of “target”, east of “target”. Note that if someone “falls” during the process, then that person’s “passive skill” will no longer take effect for the damage settlement of people after that person in this order. In particular, all “position multipliers” for these damages are computed using the “target”’s “dodge position”.
- “M”: The “target” receives “damage” whose “base attack intensity” is (the attacker’s “base attack index”) (the “weapon attack”) . The nearest not-fallen member on the west side of the “target” (if it exists) and the nearest not-fallen member on the east side of the “target” (if it exists) each receive “damage” whose “base attack intensity” is (the attacker’s “base attack index”) (the “weapon attack”) . Damage is calculated in the order: “target”, west of “target”, east of “target”. Note that if someone “falls” during the process, then that person’s “passive skill” will no longer take effect for the damage settlement of people after that person in this order. In particular, all “position multipliers” for these damages are computed using the “target”’s “dodge position”.
[Skills]
Skills are divided into “active skills” and “passive skills”. Each “race” has one “active skill” and one “passive skill”. The effects depend on “race” and “skill level”. “Skill level” is an integer between and . Level means the character does not have that skill.
Using an “active skill” requires choosing a person as the “skill target”.
The “active skill” descriptions are as follows (for level to , the effects are separated by slashes; it is guaranteed that the user’s “active skill level” is not ):
- “Weak race”: Increase the “HP” of one not-fallen ally by $\left\lfloor (\text{that member’s max HP}) \times 10\%/12\%/15\%/17\%/20\% \right\rfloor$.
- “Average race”: Choose one not-fallen enemy member. At the end of this team’s turns, their “HP” is reduced by $\left\lfloor (\text{their max HP}) \times 6\%/7\%/8\%/9\%/10\% \right\rfloor$. This effect lasts for turns, i.e. it triggers times. If the member already has an effect of the same type (possibly with a different level), this effect overrides the previous one.
- “Strong race”: Set the “skill multiplier” of one not-fallen ally to .
A member’s “passive skill” only takes effect while the member has not “fallen”. After falling, it no longer takes effect.
The “passive skill” descriptions are:
- “Weak race”: At the start of this team’s “turn”, all not-fallen members of this team increase their “HP” by of their own “max HP”. If multiple members in the team have this skill, these percentages add up, capped at (anything above is treated as ). After stacking, the amount of HP increase must be floored.
- “Average race”: The team’s “defense bonus” is initially . This skill increases the team’s “defense bonus” by . If multiple members in the team have this skill, the increases add up, capped at (anything above is treated as ).
- “Strong race”: The team’s “attack bonus” is initially . This skill increases the team’s “attack bonus” by . If multiple members in the team have this skill, the increases add up, capped at (anything above is treated as ).
When a member’s “HP” increases, it cannot exceed their “max HP”. If the increased “HP” would exceed “max HP”, then replace the effect with setting the member’s “HP” to their “max HP”.
[Skill Multiplier]
At the start of the battle, everyone’s “skill multiplier” is . There are only two ways to change the “skill multiplier”:
- The “Strong race” “active skill”. See the “Skills” description.
- After a person initiates an “attack” and all “damage” of this “attack” has been calculated, that person’s “skill multiplier” becomes .
[Race Counter Multiplier]
The “race counter multiplier” depends on the attacker’s “race” and the damaged person’s “race”. The values are shown in the following table.
| Attacker / Damaged | Weak | Average | Strong |
|---|---|---|---|
| Weak | |||
| Average | |||
| Strong |
[Position Multiplier]
When “attacking”, the attacker has an “attack position”, and the “target” has a “dodge position”. The “attack position” and “dodge position” are each an integer from to . When the “attack position” is and the “dodge position” is , the “position multiplier” is given by the following table.
| “Position multiplier” | |
|---|---|
| or | |
| or | |
Input Format
Read from standard input.
The first line contains two positive integers , representing the number of members in “South Team” and “North Team”.
The next lines describe the members of “South Team”. Line gives the information of the member with ID in “South Team”, in the following format:
<Type> Lv=<Lv> maxhp=<maxhp> atk=<atk> def=<def> skillLv=<skillLv> passivesklLv=<passivesklLv> <weapontype> weaponatk=<weaponatk>
Items in angle brackets represent variables.
<Type> is one of Weak, Average, Strong, representing the corresponding “race”.
<Lv> is an integer from to , representing the member’s “level”.
<maxhp> is an integer, representing the member’s “max HP”.
<atk> is a real number, representing the member’s “base attack index”.
<def> is a real number, representing the member’s “base defense index”.
<skillLv> is an integer from to , representing the member’s “active skill level”.
<passivesklLv> is an integer from to , representing the member’s “passive skill level”.
<weapontype> is one of B, G, M, representing the corresponding “weapon type”.
<weaponatk> is a real number, representing the member’s “weapon attack”.
The next lines describe the members of “North Team”. Line gives the information of the member with ID in “North Team”, in the same format as “South Team”.
The next line contains one positive integer , representing the number of turns.
The next lines describe the actions of each turn. Line describes the action in the -th “turn”.
An action description starts with a string indicating the action type.
Basicattack target=<target> atkpos=<atkpos> ddgpos=<ddgpos> represents a “basic attack”.
Specialattack target=<target> atkpos=<atkpos> ddgpos=<ddgpos> represents a “special attack”.
Skill target=<target> represents using an “active skill”. It is guaranteed that this member’s “skill level” is not .
Here, <target> is the ID of the “target” or “skill target”. If it is the “active skill” of the Weak race or the Strong race, then this ID is an ally’s ID; otherwise, it is an enemy’s ID.
<atkpos> is an integer from to , representing the “attack position”.
<ddgpos> is an integer from to , representing the “dodge position”.
All actions are guaranteed to be legal.
For convenience, real numbers in this problem are represented in a special way: use <mag>e<exp> to represent <mag> multiplied by to the power of <exp>. Here <mag> is a positive integer between and , and <exp> is an integer between and . For example, can be written as 42195e-3, can be written as 6e0 or 600e-2, and can be written as 4e-2.
Output Format
Write to standard output.
For each “turn”, output the information of this “turn” in chronological order.
The formats are:
<team> <id> recovered +<heal> hp -> <curhp>/<maxhp> represents the HP increase caused by the Weak race’s “skill”. If before increasing, the “HP” was already equal to “max HP”, then you do not need to output this line.
<team> <id> took <dmg> damage from <atkteam> <atkid> -> <curhp>/<maxhp> represents a member receiving “damage”.
<team> <id> took <dmg> damage from skill -> <curhp>/<maxhp> represents the HP reduction caused by the Average race’s “active skill”.
<team> <id> applied <type> skill to <targetteam> <targetid> represents using an “active skill”.
Where:
<team> is the team name, either South or North.
<id> is the member ID within the team whose HP changed, an integer from to .
<heal> is the amount of HP that should be increased (ignoring the “max HP” cap), a positive integer.
<curhp> is the “HP” after the change, a non-negative integer. If HP decreases below , output .
<maxhp> is the “max HP” of the person whose HP changed, a positive integer.
<dmg> is the received “damage” or the HP reduction caused by the Average race’s “active skill”, a non-negative integer.
<type> is the race of the person using the “active skill”, one of Weak, Average, Strong.
<atkteam> and <atkid> are the team name and ID of the attacker, in the same format as <team> and <id>.
<targetteam> and <targetid> are the team name and ID of the “skill target”, in the same format as <team> and <id>.
The chronological order is:
At the start of the “turn”, the Weak race’s “passive skill” effect may trigger; output in increasing order of IDs.
If the action is using an “active skill”, output one line of the “active skill” usage information.
Then output the HP change information caused by the action. If “damage” is , it still must be output. If no “damage” is dealt, do not output. If a “special attack” changes multiple people’s HP, output in the order: “target”, the person west of the “target”, the person east of the “target”.
At the end of the “turn”, the Average race’s “active skill” effect may trigger; output in increasing order of IDs.
After each “turn”, output the HP information of both teams in the following format:
<team>: [<curhp5>/<maxhp5>] [<curhp3>/<maxhp3>] <curhp1>/<maxhp1> [<curhp2>/<maxhp2>] [<curhp4>/<maxhp4>] [<curhp6>/<maxhp6>]
Where <team> is the team name, <curhpi> is the HP of the member with ID in the team, and <maxhpi> is the max HP of that member. There is exactly one space between the HP information of any two people, and exactly one space between the first HP information and the colon. The HP information of fallen members must also be output. The square brackets mean that if the team does not have a member with ID , then do not output that part. Note that this is in positional order rather than ID order: .
Output one line for “North Team” first, then one line for “South Team”.
Each “turn”’s output ends with a blank line.
After all turns, if one team “wins”, output one line Team <team> won. where <team> is the team name, South or North. Since an action must specify a not-fallen person as a “target” or “skill target”, and all actions are legal, if there is a winning team, it must win only after the last “turn” ends. If there is no winner, output nothing.
2 1
Strong Lv=90 maxhp=2451 atk=15588e-4 def=96931e-3 skillLv=5 passivesklLv=5 M weaponatk=80000e0
Strong Lv=100 maxhp=3512 atk=16385e-4 def=12511e-2 skillLv=5 passivesklLv=5 G weaponatk=80000e0
Weak Lv=1 maxhp=100000 atk=75000e-5 def=10000e-6 skillLv=5 passivesklLv=5 B weaponatk=80000e0
3
Skill target=2
Specialattack target=1 atkpos=3 ddgpos=3
Specialattack target=1 atkpos=5 ddgpos=5
South 1 applied Strong skill to South 2
North: 100000/100000
South: 2451/2451 3512/3512
South 1 took 1063 damage from North 1 -> 1388/2451
North: 100000/100000
South: 1388/2451 3512/3512
North 1 took 52556526 damage from South 2 -> 0/100000
North: 0/100000
South: 1388/2451 3512/3512
Team South won.
Hint
[Sample #2]
See 2.in and 2.ans under the problem directory.
[Sample Explanation #2]
This sample is undoubtedly a selfless gift from the kind problem setter. I forgot the middle part. The setter believes that this wonderful sample can provide strong help for you on the road of striving to AC this problem.
[Constraints]
It is guaranteed that .
It is guaranteed that .
It is guaranteed that the range of “weapon attack” is from to .
The ranges of “max HP”, “base attack index”, and “base defense index” are shown in the table below.
| “Race” and “Level” | “Max HP” | “Base attack index” | “Base defense index” |
|---|---|---|---|
| Weak Lv.1 | |||
| Average Lv.1 | |||
| Strong Lv.1 | |||
| Weak Lv.100 | |||
| Average Lv.100 | |||
| Strong Lv.100 |
[Epilogue]
One day I will grow old
I hope you will feel satisfied
I did not let down
That fifteen-year-old self
— Rene Liu, “Continue — To My Fifteen-Year-Old Self”
[Source]
From the final of the 2023 Tsinghua University Programming Contest and University Invitational (THUPC2023).
Editorials and other resources can be found at https://github.com/THUSAAC/THUPC2023.
Translated by ChatGPT 5