Encontrar eficientemente el máximo MCD por pares de un conjunto de números naturales

9

Considere el siguiente problema:

Sea un subconjunto finito de los números naturales.S={s1,s2,...snorte}

Deje | donde es el máximo común divisor de eg c d ( s i , s j ) s i , s jS , s is j } g c d ( x , y ) x ysol={ solCre(syo,sj)syo,sjS, syosj}solCre(X,y)Xy

Encontrar el elemento máximo de .sol

Este problema se puede resolver tomando el divisor común más grande de cada par usando el algoritmo de Euclides y haciendo un seguimiento del más grande.

¿Hay una manera más eficiente de resolver esto?

Tommy
fuente
3
Es posible que desee consultar la Sección 3.3 de Minería de Ps y Q: detección de claves débiles generalizadas en dispositivos de red (Heninger et al, Usenix Security 2012). Describen un algoritmo para calcular los gcd de pares en gcd de , en una determinada configuración, utilizando árboles de productos y árboles restantes. Sin embargo, no sé si se extiende a su problema. O(nlgn)
DW
¿Has probado algo con factorizaciones primas?
Ryan
1
Supongamos que todos los números son relativamente primos pero difíciles de factorizar (por ejemplo, cada es igual a p i q i para primos distintos grandes p i , q i ). Entonces parece difícil evitar verificar todos los GCD por pares. (Digamos que te digo que después de verificar todos los pares pero ( s n - 1 , s n ) que todos los GCD por pares son 1. ¿Cómo puedes adivinar g c d ( s n - 1 , s n ) sin calcularlo?)syopyoqyopagsyo,qyo(snorte-1,snorte)1solCre(snorte-1,snorte)
usul
El enlace de @usul DW es exactamente ese problema. Un gran número, digamos mil millones, de claves de cifrado deberían ser productos de dos primos distintos. Pero sospechamos que algunas claves de cifrado tienen un factor primo en común (que sería el mcd de ambas claves, lo que facilita su factorización). Ese algoritmo le permite encontrar las claves con factor común sin calcular n (n-1) / 2 mcd para n = 1 billón.
gnasher729

Respuestas:

-2

Aquí hay un algoritmo eficiente (en Python ). Por favor encuentre la explicación a continuación.

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

Explicación del fragmento de código anterior:

Observamos lo siguiente en este problema:

  1. El resultado no puede ser más que max(S)
  2. El resultado es un número, que tiene dos o más múltiplos en esta lista S
  3. De hecho, el resultado es maxde todos esos números con la propiedad mencionada anteriormente.

Con estas observaciones, el programa hace lo siguiente:

  1. Haga una setde la lista. Como conjuntos se pueden buscar de manera eficiente enO(log(n))
  2. Encuentre el máximo de la lista y guárdelo en la variable m.
  3. A partir de mhasta 1, encuentre el primer número que tiene dos o más múltiplos en el conjunto. El primer número encontrado es el resultado.

Espero que esto quede claro. Avíseme si necesita una explicación más detallada.

Subhendu Ranjan Mishra
fuente
1
¿Puedes explicar tu algoritmo en palabras? Este no es un sitio de programación.
Yuval Filmus
@YuvalFilmus He agregado la explicación. Espero que esto ayude.
Subhendu Ranjan Mishra
2
{2,4 4}
@YuvalFilmus para cada icomenzando con mhasta 1comprobamos si dos o más múltiplos de iestán en el conjunto. En este ejemplo, dos múltiplos de 2 están en el conjunto '2 y 4'. entonces la respuesta es 2. El whileciclo interno verifica todos los múltiplos de ihasta que m' as m` es el masx de la lista.
Subhendu Ranjan Mishra
1
X,ynorte