Secara efisien menemukan GCD berpasangan maksimum dari satu set bilangan alami

9

Pertimbangkan masalah berikut:

Biarkan menjadi subset terbatas dari bilangan asli.S={s1,s2,...sn}

Biarkan | mana adalah pembagi umum terbesar dari dang c d ( s i , s j )G={ gcd(si,sj)si,sjS, sisj}gcd(x,y)xy

Cari elemen maksimum .G

Masalah ini dapat diselesaikan dengan mengambil pembagi umum terbesar dari setiap pasangan menggunakan algoritma Euclid dan melacak yang terbesar.

Apakah ada cara yang lebih efisien untuk menyelesaikan ini?

Tommy
sumber
3
Anda mungkin ingin melihat Bagian 3.3 dari Menambang Ps dan Qs Anda: Deteksi Kunci Lemah yang Luas di Perangkat Jaringan (Heninger et al, Usenix Security 2012). Mereka menggambarkan suatu algoritma untuk menghitung gcd berpasangan di gcd, dalam pengaturan tertentu, menggunakan pohon produk dan pohon sisa. Saya tidak tahu apakah itu meluas ke masalah Anda. O(nlgn)
DW
Sudahkah Anda mencoba sesuatu dengan faktorisasi prima?
Ryan
1
Misalkan semua angka relatif prima tetapi sulit untuk faktor (misalnya setiap sama dengan untuk bilangan prima ). Maka tampaknya sulit untuk menghindari memeriksa semua GCD berpasangan. (Katakanlah saya memberi tahu Anda bahwa setelah memeriksa semua pasangan kecuali bahwa semua GCD berpasangan adalah Bagaimana Anda dapat menebak tanpa menghitungnya?)sipiqipi,qi(sn1,sn)1gcd(sn1,sn)
usul
Link @usul DW persis masalah itu. Sejumlah besar, katakan satu miliar, kunci enkripsi harus semua produk dari dua bilangan prima yang berbeda. Tetapi kami menduga bahwa beberapa kunci enkripsi memiliki faktor utama yang sama (yang akan menjadi gcd dari kedua kunci, membuat keduanya mudah menjadi faktor). Algoritme itu memungkinkan Anda menemukan kunci dengan faktor umum tanpa menghitung n (n-1) / 2 gcd untuk n = 1 miliar.
gnasher729

Jawaban:

-2

Berikut ini adalah algoritma yang efisien (dalam Python ). Silakan temukan penjelasan di bawah ini.

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

Penjelasan dari cuplikan kode di atas:

Kami mengamati hal-hal berikut dalam masalah ini:

  1. Hasilnya tidak boleh lebih dari max(S)
  2. Hasilnya adalah angka, yang memiliki dua atau lebih kelipatan dalam daftar ini S
  3. Bahkan hasilnya adalah maxsemua angka dengan properti yang disebutkan di atas.

Dengan pengamatan ini, program melakukan hal berikut:

  1. Buat setdaftar. Sebagai set dapat dicari secara efisien diO(log(n))
  2. Temukan maks dari daftar dan simpan dalam variabel m.
  3. Mulai dari mhingga 1, cari nomor pertama yang memiliki dua atau lebih kelipatan dalam set. Angka pertama yang ditemukan adalah hasilnya.

Saya harap ini jelas. Tolong beri tahu saya jika Anda membutuhkan penjelasan yang lebih rinci.

Subhendu Ranjan Mishra
sumber
1
Bisakah Anda menjelaskan algoritme Anda dengan kata-kata? Ini bukan situs pemrograman.
Yuval Filmus
@YuvalFilmus Saya telah menambahkan penjelasannya. Semoga ini membantu.
Subhendu Ranjan Mishra
2
{2,4}
@YuvalFilmus untuk setiap idimulai dengan msampai 1kita memeriksa apakah dua atau lebih kelipatan dari iyang di set. Dalam contoh ini, dua kelipatan dari 2 berada di set '2 dan 4`. jadi jawabannya adalah 2. whileLoop dalam memeriksa semua multples isampai m' as m` adalah masx dari daftar.
Subhendu Ranjan Mishra
1
x,yn