Компания Yandex организовала интересное соревнование с хорошим призовым фондом. Из 6 направлений я выбрал бэкенд, в котором по языку Java было 5 задач. Их нужно было решить за 5 часов. Я выбрал удобное время и сразу столкнулся с такой проблемой - мне было сложно понять условия задачи. Наверное стиль изложения обусловлен защитой от использования ChatGPT или это какой егэшый диалект, но после того, как задача была решена, условия сразу становятся логичными и понятными. Сразу оговорюсь, что за 5 часов я не решил ни одной (shame on you) задачи, но сейчас попытаюсь исправиться, что бы поделится опытом и возможно получить обратную связь от более опытных программистов. Для удобства каждое решение выложу в отдельной статье.


Первая задача - Арт-критика (описание под катом). 

Hidden text

Аркадий — главный редактор журнала по арт-критике. По долгу службы Аркадий постоянно сталкивается с фундаментальными вопросами "Что есть красота?”, “Как понять что красиво, а что нет?”.

Главред понимает, что искусство можно оценивать по-разному и к разным арт-объектам можно применять разные метрики. За годы работы в арт-индустрии Аркадий выработал собственный принцип оценки красоты любого произведения искусства. Он может сказать, красив арт-объект или нет, вне зависимости от количества критериев оценки "красивости".

Принцип Аркадия состоит в следующем. Для произвольного объекта искусства определяется некоторое количество критериев в определенном порядке для оценки “красивости”. По каждому критерию можно набрать максимум n первичных баллов. Вторичные баллы за условный критерий i определяются следующим образом:

  • Если при оценке критерия набирается ai первичных баллов, то Аркадий начисляет критерию a2iвторичных баллов.

  • Кроме того, Аркадий прибавляет бонусные баллы за ai следующих ненулевых оценок по другим критериям (прибавляются первичные баллы).

  • Для последнего критерия дополнительные баллы не начисляются.

Например, если n = 10, Аркадий оценивал картину по пяти критериям, и арт-объект набрал [10, 0, 1, 0, 3] первичных баллов, соответственно, то его итоговый результат будет равен 117 вторичных баллов, так как за первый критерий он получил 102 + 1 + 3 балла, за второе и четвертое — по 0, за третье — 12 + 3, за пятое — 32.

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

Формат ввода: 

В первой строке даны два целых числа n и m (1 ≤ n, m ≤ 200 000). 

Во второй строке заданы m целых чисел ai (0 ≤ ai ≤ n).

Формат вывода:

Выведите сумму набранных баллов.

Пример 1:

Ввод:

10 5

10 0 1 0 3

Вывод:

117

Пример 2:

Ввод:

5 5

0 0 0 0 0

Вывод:

0

Пример 3:

Ввод:

1 3

1 1 1

Вывод:

5

Первым делом получаем на вход два числа - максимальная оценка и количество параметров. Получим их с помощью класса Scanner:

Scanner scanner = new Scanner(System.in);

int maxScore = scanner.nextInt();

int parameterQuantity = scanner.nextInt();

Второй строкой получаем оценки. Их будем добавлять в ArrayList, потому что их количество будет меняться.

List<Integer> scoreList = new ArrayList<>();

for (int i = 0; i < parameterQuantity; i++) {

    int nextScore = scanner.nextInt();

    scoreList.add(nextScore);

}

scanner.close();

Теперь высчитываем “вторичные баллы”. Берем первое число из scoreList, возводим в квадрат, добавляем к нему остальные числа из хвоста scoreList и суммируем в какой-нибудь агрегатор. Затем выводим результат.

int acc = 0;
int tempScore;
for (int i = 0; i < parameterQuantity; i++) {
    tempScore = scoreList.get(i);
    if (tempScore == 0) continue;
    tempScore = tempScore * tempScore;
    for (int j = i + 1; j < parameterQuantity; j++) {
        if (scoreList.get(j) == 0) continue;
        tempScore += scoreList.get(j);
    }
    acc += tempScore;
}
System.out.println(acc);

Скорее всего, это неправильное решение, т.к. в третьем примере этот код выводит 6 вместо 5.

Давайте разберем этот пример, может кто-то сможет найти ошибку в решении. Итак, на вход поступают числа: 1 (максимальная оценка за один параметр), 3 (количество параметров оценивания) и три единицы (оценки по трем параметрам, которые получил арт-объект).

Берем первую оценку 1, возводим в квадрат и добавляем две единицы, получаем 3. Далее берем вторую единицу, возводим в квадрат и добавляем последнюю единицу, получаем 2. Последняя единица просто возводится в квадрат без добавлений. Итог, 3 + 2 + 1 = 6. А должно быть 5.

Следующая задача будет посложнее.

Комментарии (8)


  1. Alexandroppolus
    09.11.2023 08:00
    +2

    Похоже, в условии задачи дан ошибочный результат третьего примера. Там реально 6.

    А вообще, тут надо внешний цикл делать с конца, накапливать сумму бонусных. Тогда внутренний цикл не понадобится и будет O(n). А у вас O(n^2), что многовато для 200000.


    1. AndanteMQ Автор
      09.11.2023 08:00
      -1

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


    1. wataru
      09.11.2023 08:00
      +1

      Если я правильно понял условие, то там действительно 5 в последнем тесте.

      за ai следующих ненулевых

      Означает, что берется a_i следующих ненулевых чисел.

      Для первой единицы добавляется 1^2 и одно следующее ненулевое число (1). Для второй единицы так же. Для третьей нет больше следующих ненулевых чисел, поэтому прибавляется только 1. Вот и получается 5.


      1. Alexandroppolus
        09.11.2023 08:00

        Да, действительно. Я почему-то прочитал как "следующих за ai" :) Не уверен, что формулировка безупречна..


        1. wataru
          09.11.2023 08:00

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


    1. ageikin
      09.11.2023 08:00

      fo = 0
      so = 0
      pso = 0
      for i, k in enumerate(a[::-1]):
          fo = fo + k**2
          if k > 0 and i>0:
              so = so + pso
          pso = pso+k
      print('res', so+fo)
      >> и получаем 6 для массива из трёх единиц


      1. wataru
        09.11.2023 08:00

        Вы, как и автор, неправильно поняли условие задачи. Берутся не все следующие ненулевые элементы, а ровно a_i их. Поэтому вместо счетчика pso, вам понадобится стек с частичными суммами ненулевых элементов.


  1. wataru
    09.11.2023 08:00

    Как вам уже сказали, решение за квадрат в этой задаче скорее всего не пройдет. Надо в scoreList складывать только ненулевые числа, а также параллельно вести второй список с частичными суммами по scoreList. Тогда можно будет за одно действие найти сумму заданного количества последних ненулевых чисел, что в задаче и надо.