Algoritmo per verificare se un elenco di numeri interi è coprime a coppie


8

Esistono algoritmi efficienti per verificare se un elenco di numeri interi è coprime a coppie o un algoritmo più generale sarebbe l'opzione migliore disponibile?


Solo per essere sicuro, vuoi dire che ogni coppia di numeri interi nel tuo set è coprime?
Draconis,

2
sì, ogni combinazione di 2 numeri interi deve essere coprime
user2782067

Risposte:


8

Innanzitutto, due fatti sugli interi coprimi:

  • Iff a e b sono coprime, quindi ab=lcm(a,b)
  • Iff a è coprime per entrambi b e c, poi a è coprime a bc

Ne consegue che un insieme di interi distinti {a,b,z} è coprime a coppie se il suo prodotto è uguale al suo minimo comune multiplo.

È possibile calcolare il minimo comune multiplo utilizzando la seguente identità:

lcm(a,b,c)=lcm(a,lcm(b,c))

Supponendo che tu abbia n numeri con k cifre ciascuna e moltiplicare / dividere / modificare due numeri è O(1) (che può essere o meno un buon presupposto a seconda del modello), quindi:

  • Calcolo del prodotto del tuo set prende O(n)
  • Calcola il gcd di due numeri prende O(k)
  • Anche il calcolo del mcm di due numeri richiede quindi O(k), mediante riduzione a gcd
  • Quindi calcolare il mcm dell'intero set richiede O(nk)

Pertanto, la complessità temporale dell'intero algoritmo è O(nk).


2
Se OP lo sta effettivamente implementando, può valere la pena valutare se il prodotto / mcm sono uguali per ogni numero man mano che vengono letti piuttosto che dopo averli moltiplicati tutti / mcm tutti. Questo non cambierà la complessità, ma se ti aspetti che la maggior parte degli elenchi non sia coprime (come nel caso di un lungo elenco di numeri casuali), molto probabilmente sarà più veloce
sudo rm -rf slash

5
@DW Credo che il punto sia che, testando in modo incrementale, è possibile eseguire il salvataggio anticipato una volta trovato il primo esempio non coprime, al contrario di solo dopo aver elaborato l'intero elenco. Poiché prevediamo che la maggior parte degli elenchi non sia coprime a coppie e non abbiamo alcuna informazione sull'elenco in fase di test, dovremmo aspettarci che l'elenco probabilmente non sarà coprime a coppie e quindi procedere con una procedura ottimizzata per quel caso comune .
Andrea Reina,

@AndreaReina esattamente grazie per averlo scritto più chiaramente
sudo rm -rf slash

Un'altra nota di implementazione ... L'uso di gcd == 1 invece di lcm == prod è probabilmente più semplice dato che per quanto ne so i migliori algoritmi lcm usano comunque il gcd
sudo rm -rf slash

2
Se conti il ​​numero di cifre dei numeri, non ha senso supporre che lo siano la moltiplicazione e la divisione O(1). Loro sonoΩ(ka) per alcuni k>1.
Gilles 'SO- smetti di essere malvagio' il

4

Sì. L'approccio ingenuo di controllare ogni coppia di numeri richiede un tempo quadratico, ma esistono algoritmi più efficienti. Esiste un algoritmo temporale quasi lineare, descritto nel seguente documento:

Daniel J. Bernstein. Factoring in coprimes in un tempo essenzialmente lineare . Journal of Algorithms 54 (2005), 1--30.

Vedi anche https://cstheory.stackexchange.com/q/3393/5038 . È quasi efficiente come si potrebbe sperare.

Per chiarire come questo aiuta con la tua situazione, una volta trovata una base coprime e fattorizzato ogni elemento sulla base, è banale verificare se sono coprime a coppie: se non sono coprime a coppie, allora alcune coppie avranno un comune fattore, e questo sarà un fattore che è nella base coprime e che è presente nella fattorizzazione di entrambi. Se non è presente alcun fattore comune nella fattorizzazione di due o più numeri, allora i numeri sono coprimi a coppie. Una volta che hai le fattorizzazioni, è facile controllare in tempo lineare se ci sono numeri in più di una fattorizzazione.


2
Non vedo come si Factoring over a coprime baserelaziona checking if a list of integers is pairwise coprime(ancora).
greybeard,

@greybeard, vedi risposta modificata - Alla fine ho aggiunto un paragrafo che spiega.
DW

2

Trova i fattori primi di ciascun numero. I numeri sono tutti coprimi a coppie se e solo se ogni numero primo nell'intera raccolta è distinto. Questo controllo può essere eseguito in O (n) tempo usando una tabella hash.

Modifica: la risposta di Draconis è comunque migliore, perché non richiede alcuna fattorizzazione. Il calcolo GCD è più veloce se i tuoi numeri sono grandi e / o primi.


2
Il factoring è molto lento. Per quanto ne sappiamo, non esiste un algoritmo efficiente per il factoring - e certamente non ne conosciamo uno che richiede tempo O (n). Fondamentalmente, questo algoritmo sarà vicino al tempo esponenziale (tecnicamente, tempo sub-esponenziale ma superpolinomiale).
DW
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.