Proyek Euler Nomor 338

Saya terjebak pada masalah 338 Proyek Euler. Inilah yang telah saya lakukan sejauh ini...

Mari kita nyatakan sebuah persegi panjang dengan lebar dan tinggi masing-masing x dan y (x,y). Untuk membentuk persegi panjang baru, Anda dapat mempertimbangkan untuk memotong semacam tangga menuruni diagonal (seperti yang ditunjukkan pada uraian masalah) dengan langkah d. Namun untuk membentuk persegi panjang baru, yang berikut ini harus memuat: d|x dan (d-1)|y atau (d+1)|y. Persegi panjang baru kemudian menjadi (x/d*(d-1), y/(d-1)*d) atau (x/d*(d+1), y/(d+1)*d). Tentunya luas persegi panjang yang baru sama dengan luas persegi panjang yang lama.

Itu sudah cukup untuk mengonfirmasi bahwa G(10)=55 dan G(1000)=971745 dengan mengulang semua d yang relevan dan menambahkan semua persegi panjang baru ke suatu himpunan, berhati-hatilah untuk menghitung (x,y) dan (y,x) hanya sekali.

Masalah utama dengan metode ini adalah membuat persegi panjang baru dapat dilakukan dengan dua cara berbeda. Misalnya, (9,8) dapat berubah menjadi (6,12) dan (12,6) dengan d=3 dan d-1 atau d+1 membagi y. Atau contoh lain dari (4,4) berubah menjadi (2,8) dan (8,2) dengan d=2 dan d=1 masing-masing.

Saya kemudian cukup beruntung membaca postingan blog ini. Ini menghilangkan kebutuhan untuk memeriksa duplikat dengan mencari salah satu sisinya.

def F(w, h):
    if w&1 and h&1: return 0
    if w<h: w,h = h,w

    r = 0
    x = 1
    while x**2 <= w*h:
        if (w*h)%x!=0 or x==h:
            x += 1
            continue

        if w%(w-x)==0 or x%(x-h)==0:
            r += 1

        x += 1

    return r

def G(N):
    s = 0
    for w in range(1, N+1):
        for h in range(1, w+1):
            s += F(w,h)

    return s

G(1012) akan membutuhkan waktu yang terlalu lama untuk diselesaikan, tidak peduli seberapa cepat Fnya. Menurut saya, kita perlu menggunakan algoritma pengayakan yang mana kita mengulang semua x ‹ 1012 menghitung berapa banyak (w,h) yang memenuhi h ‹= w ‹= 1012, x|(w*h), x != h dan (w-x)|w atau (x-h)|x.

Saya pikir algoritma O(n2/3) harus dimungkinkan... tapi saya terjebak di sini!


Sunting: Saya tidak memiliki akses ke forum karena saya tidak dapat menyelesaikannya. Itu sebabnya saya meminta bantuan. Saya telah menyelesaikan sebagian besar pertanyaan lainnya dan ingin menjawab pertanyaan ini sekarang!

Sunting 2: Menurut saya, mempertimbangkan luas berdasarkan faktor prima adalah jalan buntu. Hal ini karena terdapat 1024 area yang berbeda. Persegi panjang dengan luas prima mempunyai 0 solusi, persegi panjang dengan luas semiprima mempunyai 1 solusi jika salah satu bilangan primanya adalah 2, jika tidak maka persegi panjang tersebut mempunyai 0 solusi. Namun menghitung semua solusi semiprima saja akan memakan waktu terlalu lama karena kita harus menghitung semua bilangan prima p sedemikian rupa sehingga 2*p ‹ 1024 dan hal ini tidak mungkin dilakukan.

Edit 3: Saya telah menghapus kodenya:

def G(N):
    s = 0
    for x in range(1, N):
        for h in range(1, N+1):
            if x==h: continue
            for w in range(max(h, x**2//h), N+1):
                if (w*h)%x==0 and x%(w-x)==0 and x%(x-h)==0:
                    s -= 1

    for x in range(1, N):
        for h in range(1, N+1):
            if x==h: continue
            for w in range(max(h, x**2//h), N+1):
                if (w*h)%x==0 and w%(w-x)==0:
                    s += 1

    for x in range(1, N):
        for h in range(1, N+1):
            if x==h: continue
            for w in range(max(h, x**2//h), N+1):
                if (w*h)%x==0 and h%(x-h)==0:
                    s += 1

    return s

Saya rasa memecahkan kode brute force tidak akan berhasil. Ingat, kita cukup menghitung solusi (x, w, h) untuk masing-masing submasalah tersebut. Penjumlahan terakhir akan mempunyai batasan 0 ‹ x ‹ N, 0 ‹ h ‹ N+1, x!=h, max(h, x2/h) ‹ w ‹ N+1, x|wh dan x-h|h.

Saya pikir kita harus mulai dengan asumsi bahwa suatu bilangan prima p membagi x, w, h atau bahkan x-h dan kemudian melihat apa yang dapat kita simpulkan tentang variabel lainnya. Jika itu berhasil, mungkin pertimbangkan pk untuk k yang sewenang-wenang.


person ForeverStuck    schedule 28.08.2011    source sumber
comment
Jika Anda mengalami kebuntuan, coba yang lain. Seperti yang dikatakan situs tersebut, Jika Anda tidak dapat menyelesaikannya, maka Anda tidak dapat menyelesaikannya!.   -  person hammar    schedule 28.08.2011
comment
Anda mungkin juga ingin bertanya di math.stackexchange.com   -  person agf    schedule 28.08.2011
comment
Selain itu, setelah Anda mengirimkan solusi ke Project Euler, Anda mendapatkan akses ke papan pesan untuk masalah tersebut; mungkin saja seseorang di sana telah menemukan algoritma yang optimal.   -  person Edwin    schedule 29.08.2011
comment
Dalam hal ini OP dapat kembali dan memposting jawaban terbaiknya sendiri setelah mengirimkan.   -  person smci    schedule 29.08.2011
comment
Cara lain untuk memikirkan hal ini adalah dengan menggunakan faktor prima dari bilangan tersebut, jadi dengan contoh 9 * 4 Anda memiliki 3*3 dan 2*2 yang tentu saja dapat disusun dalam tiga cara unik lainnya, 3 dan 3*2* 2, 2 dan 3*3*2, 3*2 dan 3*2. Apakah lebih cepat menghitung permutasi unik? Saya tidak tahu apakah pendekatan ini berhasil tetapi ini adalah cara lain untuk mengatasi masalah. Semoga beruntung.   -  person Jackson    schedule 30.08.2011
comment
sudahkah Anda mencetak G(0)...G(10) atau lebih dan mencari urutannya di oeis.org ?   -  person andrew cooke    schedule 03.09.2011
comment
juga, apakah ini menyederhanakan banyak hal (terutama kekhawatiran Anda tentang duplikat) untuk memisahkan contoh di halaman itu menjadi 2: dua teratas adalah slide horizontal; yang paling bawah adalah slide vertikal. itu hanya Anda d+/-1, kecuali Anda dapat melihat vertikal sebagai horizontal yang diputar. jadi Anda hanya menghitung horizontal, tetapi menyertakan kedua rotasi untuk bentuk non-persegi. mungkin itu tidak relevan tetapi mungkin menyederhanakan pembukuan.   -  person andrew cooke    schedule 03.09.2011
comment
Masalah yang menarik. Mungkin ini semua tentang menemukan metode yang tepat untuk menuliskannya. Saya kira perulangan tidak dapat dilakukan untuk parameter yang meningkat secara eksponensial. Menurut saya, mencari G sebenarnya lebih mudah daripada F, karena tidak perlu mencari faktor tetapi mempertimbangkan semuanya. Perhatikan bahwa semua persegi panjang solusi tampaknya terbuat dari N x (N+1) persegi panjang. Saya akan berpikir tentang hal ini...   -  person Gerenuk    schedule 03.09.2011
comment
Saya tidak mengerti mengapa ada +10 suara. Project Euler adalah tentang memecahkan masalah sendiri.   -  person dfens    schedule 12.09.2011


Jawaban (1)


Saya belum punya solusinya, tapi ada sesuatu yang menarik untuk Python. Saya menyadari bahwa Python dapat digunakan sebagai alat yang mudah digunakan untuk notasi algoritma! Pada dasarnya saya menulis sebuah program yang mirip dengan Anda dan mulai mengubah program secara logis sehingga hasilnya tidak berubah. saya datang dengan

def order(x,y):
    if x>=y:
        return (x,y)
    else:
        return (y,x)

N=1000
num=set()
for n in range(1, N+1):
    for a in range(1,N//n+1):
        for b in range(1,N//(n+1)+1):
            if a==b: continue
            num.add((order(a*n,b*(n+1)), order(b*n,a*(n+1))))

print(N, len(num))

Jelas sekali brute force atau bahkan loop sederhana di atas 10^12 tidak dapat dilakukan, tetapi mungkin dengan algoritma ini seseorang dapat menemukan ekspresi bentuk tertutup di beberapa titik. Jika bukan karena karakter set num, itu bisa dilakukan. Mungkin seseorang dapat menemukan titik duplikat dengan cara ini.

Ini mungkin jalan buntu, tapi tetap saja cukup keren bahwa Python dapat digunakan untuk notasi dan bekerja dengan algoritma :)

Adakah kemajuan di pihak Anda?

person Gerenuk    schedule 04.09.2011