L'OP ha osservato in un commento che ha trovato il problema etichettato come "forza bruta e DP". Che è assolutamente ridicolo. Ecco la soluzione temporale lineare:
-
Osservare che l'ordine di a, b, c è del tutto irrilevante, quindi ordinali per fare un ≥ b ≥ c.
-
Calcola g = gcd (a, b, c) (massimo comun divisore). Se n non è divisibile per g allora non c'è soluzione. Altrimenti, dividere a, b, c e n per g. Ora gcd (a, b, c) = 1.
-
Calcola g = gcd (b, c), che significa n - ai deve essere un multiplo di g. Trova i0 = il più piccolo i tale che n - ai sia un multiplo di g. Tale i esiste perché gcd (a, g) = 1. I valori possibili per i che possono portare a soluzioni sono i0, i0 + g, i0 + 2g e così via. Se n - a * i0 < 0 allora non c'è soluzione.
-
Dividi b e c per g. Ora dobbiamo trovare j, k che risolva (n - ai) / g = bj + ck, per i = i0, i0 + g, i0 + 2g e così via. gcd (b, c) è ora 1. Per ognuno di questi, sia m = (n - ai) / g, allora abbiamo bisogno di bj modulo c = m modulo c. Poiché gcd (b, c) = 1, c'è un j0 ≥ 0 più piccolo che risolve questa equazione. Gli altri valori per risolvere questo j0 + c, j0 + 2c, j + 3c. Tuttavia, ogni volta che aumentiamo j per c, dobbiamo ridurre k per b, e poiché b ≥ c questo non può migliorare la soluzione. Abbiamo k = (m - b * j0) / c, e questo k deve essere ≥ 0. L'aumento di j non può rendere k ≥ 0 se è minore di 0 per un j più piccolo. Ciò significa che per un dato i, scegliamo j = il più piccolo j tale che bj modulo c = m modulo c, e k = (m - b * j0) / c.
-
Per trovare j0 velocemente, creiamo una tabella di ricerca T mappando un valore di modulo m alla j più piccola con bj modulo c = m. Ciò avviene in tempo lineare calcolando b * 0 modulo c, b * 1 modulo c ecc. E impostando T [b * t modulo c] = t per 0 ≤ t < c.
-
L'algoritmo ora inizia con i = i0 e nessuna soluzione trovata finora. Se n - ai < 0 quindi tornare con la migliore soluzione trovata finora. Altrimenti lasciamo m = (n - ai) / g. Sia j = T [m modulo c], k = (m - b * j) / c. Se k ≥ 0 e i + j + k è meglio della soluzione migliore finora abbiamo trovato una nuova soluzione migliore. Altrimenti continua con i sostituito con i + g.
-
Acceleriamo l'algoritmo osservando che dopo aver calcolato m, sappiamo che i + j + k ≤ i + m / c che non aumenta mai. Quindi, se troviamo una soluzione e i + m / c non è maggiore di quella soluzione, possiamo uscire dall'algoritmo perché sappiamo di aver trovato una soluzione che non può essere ulteriormente migliorata.
Con l'input n = 4000, a, b, c = 1, 2, 3: riorganizziamo a = 3, b = 2, c = 1. gcd (a, b, c) = 1 so a, b , c, n rimangono invariati. g = gcd (b, c) = 1, quindi b, c sono invariati, la tabella T contiene un valore T [0] = 0.
Lasciamo i = 0, e n - ai è divisibile per g = 1. Quindi iniziamo con i = 0, m = 4000, j = T [0] = 0, k = (4000 - j * b) / c = 4000, dando la soluzione i = 0, j = 0, k = 4000.
Quindi lasciamo i = 1, m = 3997. i + m / c = 3998 < 4000, quindi la soluzione che abbiamo trovato prima è ottimale. Quindi il problema che ha superato il limite di tempo è in realtà così semplice che posso scrivere il calcolo completo. (BTW se c = 1 dopo aver diviso a, b, c, n per gcd (a, b, c), allora i = 0, j = 0, k = n, è sempre la soluzione ottimale).
Penso che la soluzione potrebbe essere sub-lineare nel tempo se troviamo O più veloce O (g) usando l'algoritmo di Euclide, e invece di costruire una tabella T in O (c) trova i valori j usando l'algoritmo di Euclide, sperando che possiamo dimostrare rapidamente che una soluzione trovata è ottimale.