<< к заданиям
Всероссийская олимпиада школьников по информатике, 6-7 класс, 2024 год
дата проведения: 23 мая 2024 - 24 мая 2024

Задача 7. Робот

ответ

Ограничение по времени: 1 секунда

На бесконечной в обе стороны клетчатой полоске в клетке с нулевой координатой стоит робот. Робот делает 1 шаг вправо, затем 2 шага влево, 3 шага вправо, 4 шага влево и так далее. Сделав суммарно N шагов, робот останавливается. Определите координату клетки, в которой окажется робот после остановки.

Формат входных данных

В единственной строке задано целое число N (0 ≤ N ≤ 1018).

Обратите внимание, что значения переменных в этой задаче могут превышать возможные значения 32-битной целочисленной переменной, поэтому необходимо использовать 64-битные целочисленные типы данных (тип int64 в языке Pascal, тип long long в C++, тип long в Java и C#).

Формат выходных данных

Выведите единственное число — координату клетки, в которой окажется робот после остановки.

Система оценки

Решения, правильно работающие при N ≤ 106, будут оцениваться в 30 баллов.

Решения, правильно работающие при N ≤ 109, будут оцениваться в 65 баллов.

Примеры

стандартный вводстандартный вывод
3−1
62

Ответ на Задачу 7.

В решении на 30 баллов можно просто промоделировать движение робота, делая по одному шагу. В этом решении в переменной direction хранится значение +1 или −1, обозначающее изменение координаты при очередном шаге. Это значение меняется на противоположное (умножается на −1), когда количество шагов curr_steps, сделанных в данном направлении, станет равно величине max_steps, которая после этого увеличивается на 1.

n = int(input())
x = 0
direction = 1
curr_steps = 0
max_steps = 1
for i in range(n):
    x += direction
    curr_steps += 1
    if curr_steps == max_steps:
        direction *= -1
        curr_steps = 0
        max_steps += 1
print(x)

Чтобы улучшить это решение и набрать 65 баллов, будем моделировать перемещения не по одному шагу, а сразу добавляя к текущей координате 1, затем вычитая 2, добавляя 3 и т.д. Одновременно с этим будем считать количество оставшихся шагов, вычитая из значения n числа 1, 2, 3, пока значение n будет положительным. Поскольку на последнем отрезке может оказаться так, что мы сможем сделать не ровно steps шагов (переменная steps будет принимать значения 1, 2, 3, ...), а меньше, т.к. иначе n станет отрицательным, то будем вычитать не значение steps, а минимум из steps и n.

n = int(input())
direction = 1
steps = 1
x = 0
while n > 0:
    x += min(steps, n) * direction
    n -= min(steps, n)
    steps += 1
    direction *= -1
print(x)

Чтобы решить задачу на 100 баллов, необходимо быстро определить, сколько полных циклов из 1, 2, 3, ... шагов пройдёт робот. Пусть это значение равно p. Тогда нужно найти такое максимальное целое p, что 1 + 2 + ... + pn. Эту сумму можно вычислить по формуле арифметической прогрессии: 1 + 2 + ... + p = p(p + 1) / 2. Итого нам нужно найти такое максимальное целое p, что p(p + 1) ≤ 2n. Вместо этого возьмём p = ⌊√(2n)⌋, округлив вниз до целого. То есть мы возьмём такое целое p, что p2 ≤ 2n, но при этом может оказаться так, что p(p + 1) > 2n. Несложно понять, что мы можем ошибиться не более, чем на 1, поэтому проверим, не возникла ли ошибка, и уменьшим значение p при необходимости.

Если было выполнено p полных циклов, то робот сделал p(p + 1) / 2 шагов, поэтому ему осталось сделать ещё np(p + 1) / 2 шагов. Дальнейшие случаи зависят от того, будет ли значение p чётным или нечётным. После выполнения 1, 2, 3, 4, 5 и т.д. полных циклов координата робота будет равна 1, −1, 2, −2, 3 и т.д. То есть при нечётном p робот закончит цикл в клетке (p + 1) / 2, а значение np(p + 1) / 2 нужно будет вычесть. При чётном p робот закончит цикл в клетке −p / 2, а значение np(p + 1) / 2 нужно будет прибавить.

n = int(input())
p = int((2 * n) ** 0.5)
if p * (p + 1) > 2 * n:
    p -= 1
if p % 2 == 1:
    x = (p + 1) // 2
    x -= n - p * (p + 1) // 2
else:
    x = -p // 2
    x += n - p * (p + 1) // 2
print(x)