Эффективно найти максимальный попарно GCD из множества натуральных чисел

9

Рассмотрим следующую проблему:

Пусть - конечное подмножество натуральных чисел.Sзнак равно{s1,s2,,,,sN}

Пусть | где - наибольший общий делитель и yg c d ( s i , s j ) s i , s jS , s is j } g c d ( x , y ) x yгзнак равно{ гсd(sя,sJ)sя,sJS, sяsJ}гсd(Икс,Y)ИксY

Найти максимальный элемент г .

Эту проблему можно решить, взяв наибольший общий делитель каждой пары с использованием алгоритма Евклида и отслеживая самый большой из них.

Есть ли более эффективный способ решения этой проблемы?

Томми
источник
3
Возможно, вы захотите взглянуть на раздел 3.3 « Разработка ваших запросов и ответов : обнаружение распространенных слабых ключей в сетевых устройствах» (Heninger et al, Usenix Security 2012). Они описывают алгоритм для вычисления попарных gcd в gcd, в определенной настройке, используя деревья продуктов и деревья остатков. Я не знаю, распространяется ли это на вашу проблему, хотя. О(NЛ.Г.N)
DW
Вы пробовали что-нибудь с простыми факторизациями?
Райан
1
Предположим, что все числа являются относительно простыми, но для (например, каждый равен для больших различных простых чисел ). Тогда, кажется, трудно избежать проверки всех парных GCD. (Скажем, я говорю вам, что после проверки всех пар, но все парные GCD равны Как вы можете угадать без его вычисления?)sяпяQяпя,Qя(sN-1,sN)1гсd(sN-1,sN)
усуль
Ссылка @usul DW именно на эту проблему. Огромное количество, скажем, один миллиард, ключей шифрования должны быть продуктами двух разных простых чисел. Но мы подозреваем, что некоторые ключи шифрования имеют главный общий фактор (который будет gcd обоих ключей, что упрощает их анализ). Этот алгоритм позволяет найти ключи с общим множителем без вычисления n (n-1) / 2 gcd для n = 1 миллиарда.
gnasher729

Ответы:

-2

Вот эффективный алгоритм (на Python ). Пожалуйста, найдите объяснение ниже.

def max_gcd_pair(S):
    # Assumption 1: S is the list of numbers
    # Assumption 2: There are no duplicates in S

    s = set(S)
    m = max(S)

    res = 0
    i = m

    while(i > 0):
        a = i
        cnt = 0
        while (a<=m): # a maxed at max of the list
            if a in s:   
               cnt += 1
            a += i

        if cnt >= 2:  # we have found the result
            res = i
            break

        i = i -1 

    return res

Объяснение приведенного выше фрагмента кода:

Мы наблюдаем следующее в этой проблеме:

  1. Результат не может быть больше чем max(S)
  2. Результатом является число, которое имеет два или более кратных в этом списке S
  3. Фактически результат - maxвсе такие числа со свойством, упомянутым выше.

С этими наблюдениями программа делает следующее:

  1. Составьте setсписок. Как наборы можно эффективно искать вO(log(n))
  2. Найдите максимум списка и сохраните его в переменной m.
  3. Начиная с mдо 1, найдите первое число, которое имеет два или более кратных в наборе. Первый найденный номер - это результат.

Надеюсь, это понятно. Пожалуйста, дайте мне знать, если вам нужно более подробное объяснение.

Субхенду Ранджан Мишра
источник
1
Можете ли вы объяснить свой алгоритм на словах? Это не сайт программирования.
Юваль
@YuvalFilmus Я добавил объяснение. Надеюсь это поможет.
Субхенду Ранджан Мишра
2
{2,4}
@YuvalFilmus для каждого , iначиная с mдо 1нас проверить , если два или более кратные из iв наборе. В этом примере два кратных 2 находятся в наборе '2 и 4'. так что ответ 2. Внутренний whileцикл проверяет все множества, iпока m' as m` не является маской списка.
Субхенду Ранджан Мишра
1
Икс,YN