Sono bloccato su Project Euler problem 338. Ecco cosa ho fatto finora ...Progetto Euler numero 338
Indichiamo un rettangolo con larghezza e altezza x
e rispettivamente (x,y)
. Per formare nuovi rettangoli, puoi considerare di tagliare una specie di scala lungo la diagonale (come mostrato nella descrizione del problema) con i passaggi di d. Ma per formare un nuovo rettangolo deve contenere: d|x
e (d-1)|y
o (d+1)|y
. Il nuovo rettangolo diventa quindi (x/d*(d-1), y/(d-1)*d)
o (x/d*(d+1), y/(d+1)*d)
. Ovviamente la nuova area dei rettangoli è la stessa del vecchio rettangolo.
Questo è stato sufficiente per confermare che G(10)=55
e G(1000)=971745
da loop attraverso tutti d pertinenti e l'aggiunta di tutti i nuovi rettangoli per un set facendo attenzione a contare (x,y)
e (y,x)
solo una volta.
Il problema principale con questo metodo è che è possibile creare un nuovo rettangolo in due modi diversi. Ad esempio, (9,8)
può essere convertito in (6,12)
e (12,6)
con d=3
e d-1
o d+1
dividendo . Oppure un altro esempio di (4,4)
si trasforma in entrambi (2,8)
e (8,2)
con d=2
e d=1
rispettivamente.
Sono stato quindi fortunato a leggere this blog post. Rimuove la necessità di controllare i duplicati cercando invece uno dei lati.
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 (10) richiederebbe troppo tempo per risolvere indipendentemente dalla velocità F è però. Penso che sia necessario o utilizzare per un qualche tipo di algoritmo di setacciatura dove il ciclo di tutti x contare quante (w, h) soddisfare h < = w < = 10 , x | (w * h) , x! = h e (wx) | w o (xh) | x.
Penso che un algoritmo O (n 2/3) sia possibile ... ma sono bloccato qui!
Edit: Non ho accesso al forum dal momento che sono in grado di risolverlo. Ecco perché sto chiedendo aiuto. Ho completato la maggior parte delle altre domande e voglio affrontare questa domanda ora!
Modifica 2: Penso che considerare le aree in base ai fattori primi sia un vicolo cieco. Questo perché ci sono 10 aree diverse. I rettangoli con aree principali hanno 0 soluzioni, i rettangoli con aree semiprime hanno 1 soluzione se uno dei primi è 2 altrimenti hanno 0 soluzioni. Ma contare da sole tutte le soluzioni semiprime richiederebbe troppo tempo poiché dovremmo contare tutti i numeri primi p tali che 2 * p che non è fattibile.
Edit 3: ho messo a nudo giù il codice:
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
Non credo che rompere il codice di forza bruta verso il basso funzionerà però. Ricorda che è sufficiente contare le soluzioni (x, w, h) su ciascuno di questi tre sottoproblemi. L'ultimo esempio somma avrebbe i vincoli 0 < x < N, 0 < h < N + 1, x = H, max (h, x/h) < w < N + 1, x |! Wh e XH | h.
Penso che dovremmo partire dal presupposto che un primo p divide x, w, h o anche x-h e quindi vedere cosa possiamo dedurre riguardo alle altre variabili. Se ciò funziona bene, si consideri p k per k arbitrari.
Se sei bloccato, prova invece un altro. Come dice il sito, "Se non riesci a risolverlo, non puoi risolverlo!" _. – hammar
Si potrebbe anche voler chiedere su math.stackexchange.com – agf
Inoltre, dopo aver inviato la propria soluzione a Project Euler, si ottiene l'accesso alle bacheche per il problema; è possibile che qualcuno abbia già trovato un algoritmo ottimale. – Edwin