Как найти такие 2 числа в последовательности, сумма которых будет кратна m?

Вводится последовательность из чисел огромной длины (размер может достигать maxInt), нужно вывести максимально быстро (ограничение 1 секунда) такие 2 числа, сумма которых будет кратна какому-либо вводимому m (если таких несколько, то вывести каждую пару). Сами числа так же могут достигать maxInt. Сложность заключается лишь в том, что последовательность очень длинная. С короткими вариантами код вполне легкий (обычный перебор). Жду предложения алгоритмов / решения. Заранее спасибо!

Upd: m != 1
  • Вопрос задан
  • 650 просмотров
Пригласить эксперта
Ответы на вопрос 6
@deliro
Жду предложения алгоритмов / решения

Жду твоего задания на любой площадке фриланса. Заранее спасибо!
Ответ написан
Комментировать
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Создаём M списков (0..M-1). Каждое получаемое число Xi записываем в список Xi % M. Затем выводим пары из списков (0, 0), (1, M-1), (2, M-2), ... (M/2, M/2).
Ответ написан
longclaps
@longclaps
Тотохен, преблема неразрешима.
Допустим, m==1. Тогда любое число (и сумма любой пары чисел) кратна m. Т.е. всего у нас maxInt*(maxInt-1)/2 пар, а ведь все их надо вывести.
зы. А еще у нас в питоне maxInt немеряный.
Ответ написан
mayton2019
@mayton2019
Bigdata Engineer
1) Поскольку в задаче нет ограничения на память - то мы можем спокойно использовать мемоизацию для хранения нужных нам ответов.
2) В процессе ввода (предполагается что ввод будет неспешный и задумчивый) чисел {n} мы строим хеш-таблицу всех возможных сочетаний пар {m(i),m(j)} где ключами будет кратность суммы этой пары. Здесь ключом будет сет чисел которые кратны этой сумме. Для простоты - табличку можно денормализовать и хранить несколько записей на 1 ключ. Например для {20,4}, будет кратность 2, 3, 4, 6, 8.
3) Еще для упрощения можно отбросить составные числа ключа (4, 6, 8) и хранить цепочку простых.
4) У этой задачи - бесконечное направление оптимизаций системы хранения этой таблицы. Зависит от дерзости автора. А он ... как видно парень очень суровый и дерзкий.
Ответ написан
Комментировать
BitNeBolt
@BitNeBolt
Ваша программа сверяет те элементы, которые уже сверяля раньше. Также, если последовательность состоит из одинаковых чисел, а делиться должно на 1 (к примеру), то ничего не выводится, хотя должно

Попробуйте следующие циклы:
for i in range(0, n):
    for j in range (i, n):
        if ((x[i] + x[j]) % m == 0):
            print(x[i], x[j])
Ответ написан
Комментировать
@noqwerty
Будем полагать, что элементы x[1],..., x[n] введенной последовательности хранятся в памяти с произвольным доступом. После ввода числа M выполняем вычисление рекуррентной последовательности y[i+1]=Mod(-M+y[g(y[i])]), где g некоторое легковычислимое отображение множества возможных значений элементов x[1],..., x[n] в множество 1,2,...,n. Далее алгоритмом Флойда определения периода находится коллизия y[i1]= y[i2]=Mod(-M+y[g(y[i2-1])]). Тогда сумма y[i1]+y[g(y[i2-1])] делится на M. Временная сложность оценивается O(Sqrt(M)) .
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы