import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Scanner; public class PrimitiveCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); List sequence = optimal_sequence(n); System.out.println(sequence.size() - 1); for (Integer x : sequence) { System.out.print(x + " "); } } public static List optimal_sequence(int n) { List sequence = new ArrayList(); int[] stepsCount = new int[n]; // the path int array indicates the next step to reduce it: // 1: minus 1 // 2: divide by 2 // 3: divide by 3 int[] path = new int[n]; int div2Steps, div3Steps, minus1Steps; for (int i = 1; i < stepsCount.length; i++) { int j = i + 1; div2Steps = Integer.MAX_VALUE; div3Steps = Integer.MAX_VALUE; if (j % 3 == 0) { div3Steps = stepsCount[j / 3 - 1]; } if (j % 2 == 0) { div2Steps = stepsCount[j / 2 - 1]; } minus1Steps = stepsCount[i - 1]; // I use a 2-dimensional array (3 by 2) as my data structure // to determine steps and path to get to the current j. Inner // 2-element array is the stepCount and path pair. This 2-dim // array is then sorted by the first element of the pair // (stepCount). This way the stepsCount and path arrays can be // built up from 1 to n eventually. int stepCountAndType[][] = { { minus1Steps, 1 }, { div2Steps, 2 }, { div3Steps, 3 } }; Arrays.sort(stepCountAndType, Comparator.comparingInt(arr -> arr[0])); stepsCount[i] = stepCountAndType[0][0] + 1; path[i] = stepCountAndType[0][1]; } sequence.add(n); while (n > 1) { int i = path[n - 1]; if (i == 3) { n = n / 3; sequence.add(n); continue; } if (i == 2) { n = n / 2; sequence.add(n); continue; } n = n - 1; sequence.add(n); } Collections.reverse(sequence); return sequence; } public static List greedy_sequence(int n) { // Greedy algo is NOT safe, therefore won't produce // the right results. List sequence = new ArrayList(); while (n >= 1) { sequence.add(n); if (n % 3 == 0) { n /= 3; } else if (n % 2 == 0) { n /= 2; } else { n -= 1; } } Collections.reverse(sequence); return sequence; } }