Individuazione efficiente del GCD massimo a coppie di un insieme di numeri naturali


9

Considera il seguente problema:

Sia un sottoinsieme finito dei numeri naturali.S={s1,s2,...sn}

Sia | dove è il massimo comun divisore di edG={ gcd(si,sj)si,sjS, sisj}gcd(x,y)xy

Trovare l'elemento massimo di .G

Questo problema può essere risolto prendendo il massimo comune divisore di ogni coppia usando l'algoritmo di Euclide e tenendo traccia di quello più grande.

Esiste un modo più efficiente per risolvere questo?


3
Potresti dare un'occhiata alla Sezione 3.3 di Mining di Ps e Q: Rilevazione di chiavi deboli diffuse nei dispositivi di rete (Heninger et al, Usenix Security 2012). Descrivono un algoritmo per calcolare gcd a coppie in gcd, in una determinata impostazione, usando alberi dei prodotti e alberi rimanenti. Non so se si estenda al tuo problema, comunque. O(nlgn)
DW

Hai provato qualcosa con prime fattorizzazioni?
Ryan,

1
Supponiamo che tutti i numeri siano relativamente primi ma difficili da considerare (ad es. Ogni è uguale a per numeri primi distinti grandi ). Quindi sembra difficile evitare di controllare tutti i GCD a coppie. (Di 'che ti dico che dopo aver controllato tutte le coppie ma che tutti i GCD a coppie sono Come hai potuto indovinare senza calcolarlo?)sipiqipi,qi(sn1,sn)1gcd(sn1,sn)
usul

Il link di @usul DW è esattamente questo problema. Un numero enorme, diciamo un miliardo, di chiavi di crittografia dovrebbero essere tutti prodotti di due numeri primi distinti. Ma sospettiamo che alcune chiavi di crittografia abbiano in comune un fattore primo (che sarebbe il gcd di entrambe le chiavi, rendendo entrambi facili da considerare). Tale algoritmo ti consente di trovare le chiavi con un fattore comune senza calcolare n (n-1) / 2 gcd per n = 1 miliardo.
gnasher729,

Risposte:


-2

Ecco un algoritmo efficiente (in Python ). Si prega di trovare la spiegazione di seguito.

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

Spiegazione dello snippet di codice sopra riportato:

Osserviamo quanto segue in questo problema:

  1. Il risultato non può essere superiore a max(S)
  2. Il risultato è un numero, che ha due o più multipli in questo elenco S
  3. In effetti il ​​risultato è maxdi tutti questi numeri con la proprietà sopra menzionata.

Con queste osservazioni, il programma procede come segue:

  1. Crea un setelenco. Poiché i set possono essere cercati in modo efficienteO(log(n))
  2. Trova il massimo dell'elenco e memorizzalo nella variabile m.
  3. A partire da mfino 1, trova il primo numero che ha due o più multipli nel set. Il primo di questi numeri trovati è il risultato.

Spero che questo sia chiaro. Per favore fatemi sapere se avete bisogno di una spiegazione più dettagliata.


1
Puoi spiegare il tuo algoritmo a parole? Questo non è un sito di programmazione.
Yuval Filmus,

@YuvalFilmus Ho aggiunto la spiegazione. Spero che sia di aiuto.
Subhendu Ranjan Mishra,

2
{2,4}

@YuvalFilmus per ogni iinizio con mfino a quando 1controlliamo se due o più multipli di isono nel set. In questo esempio due multipli di 2 sono nell'insieme '2 e 4`. quindi la risposta è 2. Il whileciclo interno controlla tutti i multipli di itill m' as m` è il masx dell'elenco.
Subhendu Ranjan Mishra,

1
x,yn
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.