Задание №27 — Оптимальный алгоритм для большого количества данных
Имеется набор данных, состоящий из пар положительных целых чисел. Необходимо выбрать из каждой пары ровно одно число так, чтобы сумма всех выбранных чисел не делилась на 35 и при этом была максимально возможной. Гарантируется, что искомую сумму получить можно.
Программа должна напечатать одно число — максимально возможную сумму, соответствующую условиям задачи.
Входные данные:
Даны два входных файла (файл А и файл В), каждый из которых содержит в первой строке количество пар N Каждая из следующих N строк содержит два натуральных числа, не превышающих 10000.
В ответе укажите два числа: сначала значение искомой суммы для файла А, затем для файла В.
Пример организации исходных данных во входном файле:
6
1 3
5 12
6 9
5 4
3 3
1 1
Для указанных входных данных значением искомой суммы должно быть число 33.
Типовой пример имеет иллюстративный характер. Для выполнения задания используйте данные из прилагаемых файлов.
Предупреждение: для обработки файла B не следует использовать переборный алгоритм, вычисляющий сумму для всех возможных вариантов, поскольку написанная по такому алгоритму программа будет выполняться слишком долго.
Правильный ответ
665848 665534337
Пояснение
Решение:
Сначала забудем про делимость и возьмём из каждой пары большее число. Полученная сумма — наибольшая из всех возможных, поэтому если она не делится на 35, то она и есть ответ.
Пусть делится на 35. Тогда в некоторых парах придётся взять меньшее число. Замена в паре уменьшает сумму ровно на , а замены в нескольких парах — на сумму соответствующих разностей. Итоговая сумма не делится на 35 тогда и только тогда, когда не кратна 35 (ведь само кратно 35). Но если бы все слагаемые в были кратны 35, то и вся сумма была бы кратна 35; значит, хотя бы одна разность не кратна 35, и потому , где — наименьшая положительная разность, не кратная 35. Эта оценка достижима: достаточно поменять выбор в одной-единственной паре. Итак, ответ равен , если не делится на 35, и иначе.
Алгоритм линейный: один проход по файлу, в котором накапливаются и .
def solve(name, m):
f = open(name)
n = int(f.readline())
s = 0 # сумма больших чисел из каждой пары
best = 10**9 # минимальная «допустимая» разность
for _ in range(n):
a, b = map(int, f.readline().split())
s += max(a, b)
d = abs(a - b)
if d > 0 and d % m != 0:
best = min(best, d)
if s % m != 0:
return s
return s - best
print(solve('A.txt', 35), solve('B.txt', 35))Файл A: сумма больших чисел равна ; она даёт остаток при делении на 35, то есть уже не делится на 35 — уменьшать ничего не нужно, ответ .Файл B: сумма больших чисел равна и делится на 35. Наименьшая ненулевая разность внутри пары, не кратная 35, равна , поэтому ответ .Ответ: 665848 665534337