Решить задачу на python,оптимизировать
n = int(input())
total_sum = n * (n + 1) // 2
count = 0
# Перебираем все возможные позиции начала и конца.
for i in range(1, n + 1):
for j in range(i, n + 1):
removed_sum = (j * (j + 1)) // 2 - ((i - 1) * i) // 2
if total_sum - removed_sum == removed_sum:
count += 1
print(count)
Задача E. Erasing numbers
Входной файл: Стандартный вход
Ограничение времени: 1 сек
Выходной файл: Стандартный выход
Ограничение памяти: 256 Мб
Условие
В Научно-исследовательском институте, где работает Тимофей, продолжается успешное исследование
ряда натуральных чисел. Каждый день его коллеги открывают всё новые и новые свойства этой
последовательности, и Тимофей старается от них не отставать. Сегодня Тимофей, как обычно, выписал
на доске в ряд натуральные числа от 1 до и пытается ответить на вопрос, возможно ли стереть в
середине списка несколько (не менее одного) чисел, идущих подряд, чтобы сумма оставшихся чисел
слева равнялась сумме оставшихся чисел справа?
Формат входных данных
Единственная строка входных данных содержит натуральное число .
Формат выходных данных
Выведите в первой строке неотрицательное целое число — количество различных способов стереть
числа.
Ограничения
3 ≤ n ≤ 10^5
Пояснения к примерам.
В первом примере дано . Перечислим все способы стереть числа в середине ряда:
1 # 3 4 5
1 2 # 4 5
1 2 3 # 5
1 # # 4 5
1 2 # # 5
1 # # # 5
Ни в одном из них нужное свойство не достигается. Во втором примере дано . Перечислим все хорошие способы стереть числа в середине ряда:
1 2 3 4 5 6 # # # ## ## ## ## ## ## ## ## ## ## ## 21
1 2 3 4 5 6 7 8 9 10 11 12 ## ## ## ## ## 18 19 20 21
В первом списке сумма чисел слева и справа равны 21, во втором — 78. Всего два способа.
Ответы (1 шт):
Тут явно напрашивается одна из типовых методик для решения алгоритмических задач - "метод двух указателей".
- Делаем два указателя - на начало списка и на конец списка
- Идём по условиям (см. ниже) с начала списка вперёд первым указателем и с конца к началу вторым указателем
- Попутно аккумулируем две суммы - от начала списка до первого указателя и от второго указателя до конца списка
- В зависимости от того, равны суммы или какая-то из них больше, либо увеличиваем список найденных вариантов, либо сдвигаем тот указатель, чья сумма меньше
- Когда указатели встретятся, выводим результат
Сложность получается O(n), по идее этого вполне достаточно. Но в дальнейшем я бы проверил, может левый указатель нужно сдвигать не по одной позиции, а воспользоваться двоичным поиском, для больших последовательностей это должно даль дополнительную оптимизацию.
Можно вспомнить ещё формулы для суммы чисел ряда, возможно они тоже дадут какую-то оптимизацию, но это нужно ещё подумать. Возможно, это позволит сдвигать левый указатель сразу на вычисленную позицию, пересчитав её из разницы сумм и текущего числа под левым указателем.
Код сами напишите, он совсем не сложный, тут главное алгоритм придумать.