Так как я решил это прошлой ночью, я думал, что выложу свое решение C ++. Алгоритм начинается с первоначального предположения, расположенного на глобальном максимуме непрерывного случая. Затем он ищет «немного» слева / справа от первоначального предположения, заканчивая рано, когда непрерывный случай падает ниже уже установленного максимума. Интересно, что 5 примеров ответов, опубликованных ФБ, содержали 3 неправильных ответа:
Case #1
ours: 21964379805 dmg: 723650970382348706550
theirs: 21964393379 dmg: 723650970382072360271 Wrong
Case #2
ours: 1652611083 dmg: 6790901372732348715
theirs: 1652611083 dmg: 6790901372732348715
Case #3
ours: 12472139015 dmg: 60666158566094902765
theirs: 12472102915 dmg: 60666158565585381950 Wrong
Case #4
ours: 6386438607 dmg: 10998633262062635721
theirs: 6386403897 dmg: 10998633261737360511 Wrong
Case #5
ours: 1991050385 dmg: 15857126540443542515
theirs: 1991050385 dmg: 15857126540443542515
Наконец, код (он использует libgmpxx для больших чисел). Я сомневаюсь, что код является оптимальным, но он завершается за 0,280 мс на моем персональном компьютере для примера ввода, данного FB ....
#include <iostream>
#include <gmpxx.h>
using namespace std;
typedef mpz_class Integer;
typedef mpf_class Real;
static Integer getDamage( Integer g, Integer G, Integer W, Integer M)
{
Integer w = (M - g * G) / W;
return g * w;
}
static Integer optimize( Integer G, Integer W, Integer M)
{
Integer initialNg = M / ( 2 * G);
Integer bestNg = initialNg;
Integer bestDamage = getDamage ( initialNg, G, W, M);
// search left
for( Integer gg = initialNg - 1 ; ; gg -- ) {
Real bestTheoreticalDamage = gg * (M - gg * G) / (Real(W));
if( bestTheoreticalDamage < bestDamage) break;
Integer dd = getDamage ( gg, G, W, M);
if( dd >= bestDamage) {
bestDamage = dd;
bestNg = gg;
}
}
// search right
for( Integer gg = initialNg + 1 ; ; gg ++ ) {
Real bestTheoreticalDamage = gg * (M - gg * G) / (Real(W));
if( bestTheoreticalDamage < bestDamage) break;
Integer dd = getDamage ( gg, G, W, M);
if( dd > bestDamage) {
bestDamage = dd;
bestNg = gg;
}
}
return bestNg;
}
int main( int, char **)
{
Integer N;
cin >> N;
for( int i = 0 ; i < N ; i ++ ) {
cout << "Case #" << i << "\n";
Integer G, W, M, FB;
cin >> G >> W >> M >> FB;
Integer g = optimize( G, W, M);
Integer ourDamage = getDamage( g, G, W, M);
Integer fbDamage = getDamage( FB, G, W, M);
cout << " ours: " << g << " dmg: " << ourDamage << "\n"
<< " theirs: " << FB << " dmg: " << fbDamage << " "
<< (ourDamage > fbDamage ? "Wrong" : "") << "\n";
}
}