First, congrats for those who manage to solve the question. I didn't manage that with literally every single formula derived wrongly.
BTW, after fixing those formulas and applying the ideas from the analysis, I have the file at the bottom of the message. What confuse me is the time to run the solution. It takes about 6 minutes in my i7-4790, and most of the time of course goes to the debuff simulation which is O(n) where n = knight_attack / debuff. I've double checked that my binary is compiled with -O2. It means: if I am to run the code in a slower computer (e.g. an AMD E-350), the code will fail the time limit. I've also timed Eryx's solution in my computer. It's a bit faster than my solution here, but only faster for less than a minute, so the big picture is still the same. Didn't try the other six solutions, but they all appear to do the same simulation as Eryx, so the time needed to run shouldn't be very surprising. So I'll put my questions here: (1) is there a better algorithm to do this? (2) did anyone tried using multiple threads? (This should run 4 times faster in the i7-4790, but note that my E-350 is 20 times slower than the i7-4790, so threading likely won't help.) (3) DID ANYONE HAVE THE TIMER EXPIRED ONLY BECAUSE YOU'RE USING A SLOWER CPU? If yes please post up here. Regards, WC Leung. (p.s. I still managed to get to round 2. So see you there!) // Compile with MinGW-64 (6.3.0) in MSYS2 // Compile switches: -std=c++11 -Wall -Wconversion -Werror #include <stdint.h> #include <algorithm> #include <cmath> #include <iomanip> #include <iostream> #include <map> #include <string> #include <queue> #include <vector> using namespace std; const int64_t maxint = 20000000000ll; int64_t DivCeiling(int64_t n, int64_t d) { return (n-1) / d + 1; } int64_t GetTurnsWithBuff(int64_t hit, int64_t attack, int64_t buff, int64_t buff_turns) { return buff_turns + DivCeiling(hit, attack + buff * buff_turns); } struct DataAfterDebuff { int64_t hit; int64_t attack; int64_t turns; }; DataAfterDebuff GetDataAfterDeBuff(DataAfterDebuff original_data, int64_t hit, int64_t debuff, int64_t debuff_turns) { DataAfterDebuff data = original_data; for (int64_t i = 0; i < debuff_turns; ++i) { data.turns ++; data.attack -= debuff; if (data.attack < 0) { data.attack = 0; return data; // unable to kill } data.hit -= data.attack; if (data.hit <= 0) { data.turns++; data.hit = hit - data.attack - data.attack - debuff; } } return data; } void solve(int caseNo) { std::cout << "Case #" << caseNo << ": "; int64_t d_hit, d_attack, k_hit, k_attack, buff, debuff; cin >> d_hit >> d_attack >> k_hit >> k_attack >> buff >> debuff; int64_t attack_turns = maxint; for (int64_t i = 0; i+1 < attack_turns; ++i) { int64_t new_attack_turns = GetTurnsWithBuff(k_hit, d_attack, buff, i); if (new_attack_turns > attack_turns) break; attack_turns = std::min(attack_turns, new_attack_turns); } if ((attack_turns > 1 && (k_attack - debuff) >= d_hit) || (attack_turns > 2 && (k_attack * 2 - debuff * 3) >= d_hit)) { cout << "IMPOSSIBLE" << "\n"; return; } int64_t debuff_turns = 0; int64_t real_turns = maxint; int64_t endurance = 0; DataAfterDebuff data = {d_hit, k_attack, 0}; for ( ; ; ) { // if debuff_turns > 0, get the turns needed for the next endurance. int64_t max_attack = endurance > 0 ? DivCeiling(d_hit, endurance) - 1 : maxint; debuff_turns = debuff > 0 ? std::max(0ll, DivCeiling(k_attack - max_attack, debuff)) : 0; data = GetDataAfterDeBuff(data, d_hit, debuff, debuff_turns > 0 ? debuff_turns - (k_attack - data.attack) / debuff : 0); //cout << data.hit << ' ' << data.attack << ' ' << data.turns << '\n'; int64_t current_turns; if (data.attack <= 0 || DivCeiling(data.hit, data.attack) >= attack_turns) { current_turns = data.turns + attack_turns; endurance = data.attack <= 0 ? maxint : DivCeiling(d_hit, data.attack); } else { int64_t first_attack_turns = DivCeiling(data.hit, data.attack) - 1; int64_t remaining_attack_turns = attack_turns - first_attack_turns; endurance = DivCeiling(d_hit, data.attack); if (endurance < 3) continue; int64_t heal_turns = remaining_attack_turns < 2 ? 1 : (remaining_attack_turns - 2) / (endurance - 2) + 1; current_turns = data.turns + attack_turns + heal_turns; } real_turns = std::min(real_turns, current_turns); if (data.attack <= 0 || debuff == 0) break; } cout << real_turns << "\n"; } int main(int argc, char** argv) { int N; std::cin >> N; std::string str; std::getline(std::cin, str); for (int i = 0; i < N; ++i) { solve(i + 1); } return 0; } -- You received this message because you are subscribed to the Google Groups "Google Code Jam" group. To unsubscribe from this group and stop receiving emails from it, send an email to google-code+unsubscr...@googlegroups.com. To post to this group, send email to google-code@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/google-code/4b883d47-553f-4049-ba1a-7b44e6ae991d%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.