/* HackerRank Template v0.26 by Sergey Esipenko */ import java.io.*; import java.util.*; import static java.lang.Math.*; import static java.util.Arrays.fill; import static java.util.Arrays.sort; public class Solution implements Runnable { /* START OF SOLUTION */ static final Random RANDOM = new Random(7777L); static final int MAX_MONEY = 12000; void solve() throws IOException { final int nTests = nextInt(); for (int testIdx = 1; testIdx <= nTests; testIdx++) { solveTestCase(testIdx); } } int A, B, C; int tick = 1; int[] cacheVersion = new int [MAX_MONEY + 1]; long[] cache = new long [MAX_MONEY + 1]; void solveTestCase(int testIdx) throws IOException { final long seqLength = nextLong(); A = nextInt(); B = nextInt(); C = nextInt(); cacheVersion[0] = ++tick; cache[0] = 1L; for (int money = 0; money <= MAX_MONEY; money++) { final long curMaxLength = maxLength(money); if (curMaxLength >= seqLength) { out.println(money); return; } } throw new RuntimeException("MAX_MONEY is too small!"); } long maxLength(final int money) { if (money < 0) return 0L; if (cacheVersion[money] != tick) { cache[money] = max(maxLength(money - 1), maxLength(money - A) + maxLength(money - B) + maxLength(money - C)); cacheVersion[money] = tick; } return cache[money]; } /* END OF SOLUTION */ /************************************************************************** * Entry point *************************************************************************/ static final Solution INSTANCE = new Solution(); static final boolean WRITE_LOG = true; static final long STACK_SIZE = 1L << 24; // < 0 for default stack size static long initTime; static boolean localRun = false; @SuppressWarnings("unused") public static void main(String[] args) throws IOException { try { initTime = System.currentTimeMillis(); try { localRun = "true".equals(System.getProperty("LOCAL_RUN_7777")); if (localRun && new File("input.txt").exists()) System.setIn(new FileInputStream("input.txt")); } catch (SecurityException e) { // Can't get property. It seems that solution is running in a secure // environment } if (STACK_SIZE < 0L) { INSTANCE.run(); } else { new Thread(null, INSTANCE, "Solver", 1L << 24).start(); } } catch (Throwable e) { e.printStackTrace(); System.exit(999); } } @Override public void run() { try { in = new BufferedReader(new InputStreamReader(System.in)); out = new PrintWriter(System.out); solve(); out.close(); in.close(); writeLog("Total time: " + (System.currentTimeMillis() - initTime) + " ms"); writeLog("Memory status: " + memoryStatus()); } catch (Throwable e) { e.printStackTrace(); System.exit(999); } } /************************************************************************** * Input *************************************************************************/ BufferedReader in; PrintWriter out; StringTokenizer st = new StringTokenizer(""); String nextToken() throws IOException { while (!st.hasMoreTokens()) st = new StringTokenizer(in.readLine()); return st.nextToken(); } int nextInt() throws IOException { return Integer.parseInt(nextToken()); } long nextLong() throws IOException { return Long.parseLong(nextToken()); } double nextDouble() throws IOException { return Double.parseDouble(nextToken()); } int[] nextIntArray(int size) throws IOException { int[] ret = new int [size]; for (int i = 0; i < size; i++) ret[i] = nextInt(); return ret; } long[] nextLongArray(int size) throws IOException { long[] ret = new long [size]; for (int i = 0; i < size; i++) ret[i] = nextLong(); return ret; } double[] nextDoubleArray(int size) throws IOException { double[] ret = new double [size]; for (int i = 0; i < size; i++) ret[i] = nextDouble(); return ret; } String nextLine() throws IOException { st = new StringTokenizer(""); return in.readLine(); } boolean isEof() throws IOException { while (!st.hasMoreTokens()) { String s = in.readLine(); if (s == null) return true; st = new StringTokenizer(s); } return false; } /************************************************************************** * Output *************************************************************************/ void printIf(final boolean condition, final String msgIfTrue, final String msgIfFalse) { out.println(condition ? msgIfTrue : msgIfFalse); } void printRepeat(String s, int count) { for (int i = 0; i < count; i++) out.print(s); } void printArray(int[] array) { if (array == null || array.length == 0) return; for (int i = 0; i < array.length; i++) { if (i > 0) out.print(' '); out.print(array[i]); } out.println(); } void printArray(long[] array) { if (array == null || array.length == 0) return; for (int i = 0; i < array.length; i++) { if (i > 0) out.print(' '); out.print(array[i]); } out.println(); } void printArray(double[] array) { if (array == null || array.length == 0) return; for (int i = 0; i < array.length; i++) { if (i > 0) out.print(' '); out.print(array[i]); } out.println(); } void printArray(double[] array, String spec) { if (array == null || array.length == 0) return; for (int i = 0; i < array.length; i++) { if (i > 0) out.print(' '); out.printf(Locale.US, spec, array[i]); } out.println(); } void printArray(Object[] array) { if (array == null || array.length == 0) return; boolean blank = false; for (Object x : array) { if (blank) out.print(' '); else blank = true; out.print(x); } out.println(); } @SuppressWarnings("rawtypes") void printCollection(Collection collection) { if (collection == null || collection.isEmpty()) return; boolean blank = false; for (Object x : collection) { if (blank) out.print(' '); else blank = true; out.print(x); } out.println(); } /************************************************************************** * Utility *************************************************************************/ static String memoryStatus() { return (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() >> 20) + "/" + (Runtime.getRuntime().totalMemory() >> 20) + " MB"; } static void checkMemory() { System.err.println(memoryStatus()); } static long getRunningTime() { return System.currentTimeMillis() - initTime; } static void chk(boolean f) { if (!f) throw new RuntimeException("Assert failed"); } static void chk(boolean f, String format, Object ... args) { if (!f) throw new RuntimeException(String.format(format, args)); } static void writeLog(String format, Object... args) { if (localRun && WRITE_LOG) System.err.println(String.format(Locale.US, format, args)); } static void swap(int[] a, int i, int j) { int tmp = a[i]; a[i] = a[j]; a[j] = tmp; } static void swap(long[] a, int i, int j) { long tmp = a[i]; a[i] = a[j]; a[j] = tmp; } static void swap(double[] a, int i, int j) { double tmp = a[i]; a[i] = a[j]; a[j] = tmp; } static void swap(Object[] a, int i, int j) { Object tmp = a[i]; a[i] = a[j]; a[j] = tmp; } static void shuffle(int[] a, int from, int to) { for (int i = from; i <= to; i++) swap(a, i, from + RANDOM.nextInt(i - from + 1)); } static void shuffle(long[] a, int from, int to) { for (int i = from; i <= to; i++) swap(a, i, from + RANDOM.nextInt(i - from + 1)); } static void shuffle(double[] a, int from, int to) { for (int i = from; i <= to; i++) swap(a, i, from + RANDOM.nextInt(i - from + 1)); } static void shuffle(Object[] a, int from, int to) { for (int i = from; i <= to; i++) swap(a, i, from + RANDOM.nextInt(i - from + 1)); } static void shuffle(int[] a) { if (a == null) return; shuffle(a, 0, a.length - 1); } static void shuffle(long[] a) { if (a == null) return; shuffle(a, 0, a.length - 1); } static void shuffle(double[] a) { if (a == null) return; shuffle(a, 0, a.length - 1); } static void shuffle(Object[] a) { if (a == null) return; shuffle(a, 0, a.length - 1); } static long[] getPartialSums(int[] a) { final long[] sums = new long [a.length + 1]; for (int i = 0; i < a.length; i++) sums[i + 1] = sums[i] + a[i]; return sums; } static long[] getPartialSums(long[] a) { final long[] sums = new long [a.length + 1]; for (int i = 0; i < a.length; i++) sums[i + 1] = sums[i] + a[i]; return sums; } static int[] getOrderedSet(int[] a) { final int[] set = Arrays.copyOf(a, a.length); if (a.length == 0) return set; shuffle(set); sort(set); int k = 1; int prev = set[0]; for (int i = 1; i < a.length; i++) { if (prev != set[i]) { set[k++] = prev = set[i]; } } return Arrays.copyOf(set, k); } static long[] getOrderedSet(long[] a) { final long[] set = Arrays.copyOf(a, a.length); if (a.length == 0) return set; shuffle(set); sort(set); int k = 1; long prev = set[0]; for (int i = 1; i < a.length; i++) { if (prev != set[i]) { set[k++] = prev = set[i]; } } return Arrays.copyOf(set, k); } static int gcd(int x, int y) { x = abs(x); y = abs(y); while (x > 0 && y > 0) { if (x > y) { x %= y; } else { y %= x; } } return x + y; } static long gcd(long x, long y) { x = abs(x); y = abs(y); while (x > 0 && y > 0) { if (x > y) { x %= y; } else { y %= x; } } return x + y; } }