Разбор Задач Заочного Тура Школы Программистов Headhunter 2016. Часть 1

Добрый день всем! Крайний срок приема заявок – 30 сентября.

Школа программирования HeadHunter 2016 .

В этой статье мне бы хотелось проанализировать задачи заочного этапа.

Надеюсь, что моя статья будет полезна, учитывая, что при решении задач мне пришлось посетить не один десяток сайтов.

Опыт программирования у меня небольшой, поэтому не утверждаю, что мое решение единственно правильное.

Всегда буду рад услышать вашу критику! Язык программирования Java используется для решения проблем.

Статья исправлена с помощью комментариев пользователей: при решении первой задачи использован один цикл, при вычислении факториала натурального числа вместо long используется тип BigInteger, исправлена вторая проблема.



Проблема 1

Дано равенство, в котором цифры заменены буквами: rqr + rqq = sqr. Найдите, сколько у него решений, если разным числам соответствуют разные буквы (в числе нет ведущих нулей).

Для решения этой задачи можно выбрать два пути: решить ее в лоб, используя три вложенных цикла.

для или преобразуйте выражение и используйте только два вложенных цикла для .

Выберем второй путь.

Буквы в выражении условий задачи являются числами, а это значит, что каждая из них варьируется от 0 до 9 .

Теперь давайте вспомним представление числа в десятичная система счисления и преобразуем выражение к следующему виду: s = 2r + 0,11q .

Тогда код решения задачи будет выглядеть так: Старое решение

  
  
  
  
  
  
  
  
  
  
  
   

public class FirstTask { public static void main(String[] args){ int count = 0; for (int q = 0; q < 10; q++){ for (int r = 1; r < 10; r++){ if ((r != q)){ double s = 2 * r + 0.11 * q; if (s % 1 == 0 && s != 0 && s < 10) count++; } } } System.out.println("count is " + count); } }

В постановке задачи указано, что ведущих нулей быть не должно; исходя из этого были выбраны начальные значения переменных.

Для переменной с необходимо использовать тип двойной за правильное выполнение условия с % 1 == 0 .

Эта программа учитывает следующие тождества:

101 + 100 = 201.0 202 + 200 = 402.0 303 + 300 = 603.0 404 + 400 = 804.0 count is 4

Учитывая, что д = 0 , то у нас есть только один цикл:

public class FirstTask { public static void main(String[] args){ int count = 0; for (int r = 1; 2 * r < 10; r++) count++; System.out.println("count is " + count); } }



Проблема 2

Наименьшее число m такое, что m! делящийся на 10 без остатка равен m=5 (5!=120).

Аналогично, наименьшее число m такое, что m! делится без остатка на 25, это m=10. В общем случае значение функции s(n) равно наименьшему числу m такому, что m! Делится на n без остатка.

Определим функцию S(M, N) = ∑s(n) для всех n ∈ [M, N].

Например, S(6, 10) = 3 + 7 + 4 + 6 + 5 = 25. Найдите S(2300000, 2400000).

Разобьем задачу на несколько этапов.

Нам нужно построить метод, вычисляющий факториал натурального числа (метод факториал (BigInteger м) ), вычисляя значение м , удовлетворяющий условиям задачи (метод мод (BigInteger n) ) и метод, вычисляющий значение функции С(М, Н) (метод решить (BigInteger n, BigInteger m) ).

Обратите внимание, что в постановке задачи нужно найти значение функции С(2300000, 2400000) , факториал аргументов которого будет большим числом, поэтому для всех числовых переменных мы используем тип БигИнтегер (иначе расчеты будут неверными).

Метод факториал (BigInteger м) реализовать с помощью цикла: текущая переменная в отставку умножить на переменную цикла для а затем присваивайте ему результат до тех пор, пока не будут завершены все итерации цикла.

Метод мод (BigInteger n) ищет наименьшее значение м , что удовлетворяет условиям задачи: факториал(м) % n == 0 .

Для выбора таких значений используем цикл для .

Как только это м нашли, выходим из цикла.

Метод решить (BigInteger n, BigInteger m) вычисляет сумму всех значений, полученных с помощью метода мод (BigInteger n) используя цикл для , переменная которого варьируется от н до м с шагом в единицу.

Старое решение с использованием BigInteger

public class SecondTask { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BigInteger n = BigInteger.valueOf(Integer.parseInt(br.readLine())); BigInteger m = BigInteger.valueOf(Integer.parseInt(br.readLine())); solve(n,m); } public static BigInteger factorial(BigInteger n) { BigInteger res = BigInteger.ONE; if (n.intValue() == 0 || n.intValue() == 1) return res; else { for (BigInteger i = BigInteger.ONE; i.compareTo(n) <= 0; i = i.add(BigInteger.ONE)) { res = res.multiply(i); } } return res; } public static BigInteger s(BigInteger n) { BigInteger res = BigInteger.ZERO; for (BigInteger m = BigInteger.ZERO; m.compareTo(n) <= 0; m = m.add(BigInteger.ONE)) { System.out.println("m = " + m); if ((factorial(m)).

mod(n).

equals(BigInteger.ZERO)) { res = m; break; } } return res; } public static BigInteger solve(BigInteger N, BigInteger M){ BigInteger res = BigInteger.ZERO; for (BigInteger i = N; i.compareTo(M) <= 0; i = i.add(BigInteger.ONE)){ BigInteger m = s(i); res = res.add(m); } return res; }

Тестирование примера программы в постановке задачи С(6, 10) :

6 10 25

Результат выполнения программы за С(2300000, 2400000) (использовался тип длинный :

2300000 2400000 6596625

Для решения этой проблемы используется алгоритм Комментарии .



public class SecondTask { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); int m = Integer.parseInt(br.readLine()); Date startSolve = new Date(); solve(n, m); Date finishSolve = new Date(); long solveTime = finishSolve.getTime() - startSolve.getTime(); System.out.println("solveTime is " + solveTime + " ms"); } public static int s(int n) { TreeMap<Integer, Integer> treemap = new TreeMap<Integer, Integer>(); int i = 2, count = 1; while (i <= n){ if (n % i == 0){ if (treemap.containsKey(i)){ count++; treemap.put(i, count); } else { count = 1; treemap.put(i, count); } n = n / i; i--; } i++; } int p = treemap.lastKey(), k = treemap.get(treemap.lastKey()), m = 0; if (k > p){ do k--; while(k > p); m = k * p; } else m = k * p; return m; } public static int solve(int n, int m){ int res = 0; for (int i = n; i <= m; i++) res += s(i); System.out.println(res); return res; } }

Тестирование примера программы в постановке задачи С(6, 10) :

6 10 25 solveTime is 0 ms

Результат выполнения программы за С(2300000, 2400000) :

2300000 2400000 1796256390 solveTime is 130854 ms



Проблема 3

Рассмотрим все возможные числа a б за 1 б для 2 Чтобы возвести число в степень, мы используем метод Math.pow(x,y) (зачем изобретать велосипед?).

Однако при использовании этого метода необходимо, чтобы все числовые переменные имели тип двойной .

Решаем задачу с помощью двух коллекций: ArrayList используется для добавления элементов а б , Хэшсет используется для удаления всех повторяющихся элементов из коллекции.



public class ThirdTask { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.println("type the interval for a"); double a1 = Long.parseLong(br.readLine()); double a2 = Long.parseLong(br.readLine()); System.out.println("type the interval for b"); double b1 = Long.parseLong(br.readLine()); double b2 = Long.parseLong(br.readLine()); pow(a1, a2, b1, b2); } public static ArrayList<Double> pow(double a1, double a2, double b1, double b2){ ArrayList<Double> arr = new ArrayList<>(); for (double i = a1 + 1; i < a2; i++){ for (double j = b1 + 1; j < b2; j++){ arr.add(Math.pow(i,j)); } } System.out.println("arr size is " + arr.size()); HashSet<Double> list = new HashSet<Double>(arr); System.out.println("now arr size is " + list.size()); return arr; } }

Тестирование программы на 1
И 1 :

type the interval for a 1 6 type the interval for b 1 6 arr size is 16 now arr size is 15

Результат выполнения программы за 2
И 2 :

type the interval for a 2 135 type the interval for b 2 136 arr size is 17556 now arr size is 16640

Статья получилась довольно длинной, а впереди еще две объемные задачи, в которых нам нужно проанализировать логику перебора элементов.

Остальные задачи разберем в следующей публикации.

Теги: #java #Занимательные задачи #программирование #java #Алгоритмы

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.