Perché non leggere l'articolo di Frye? Ecco un riassunto. Hai bisogno dell'aritmetica modulare per setacciare i candidati. Mod 5 funziona come il fascino (200 volte la riduzione dello spazio di ricerca). Devi dividerlo in A ^ 4 + B ^ 4 e D ^ 4-C ^ 4. Il programma stesso è scritto in Lisp.
L'implementazione è ragionevolmente semplice, mentre la matematica sottostante è accurata. Primo: setaccia alcuni numeri usando l'aritmetica modulare. Quindi studia A ^ 4 + B ^ 4 e D ^ 4 - C ^ 4 trasformando il problema in O (n ^ 2)
In primo luogo, osserva che il mod 5 è molto restrittivo.
A A ^ 4 A ^ 4 mod 5
0 0 0
1 1 1
2 16 1
3 81 1
4 256 1
Quindi, un controesempio deve soddisfare questi due requisiti:
Un mod 5 = B mod 5 = 0 // A e B sono divisibili per 5
C ^ 4 mod 5 = D ^ 4 mod 5 = 1 // il promemoria della divisione è 1
Si noti che D è il numero più grande e non è divisibile per 5, C non è divisibile per 5. A < B, A e B sono divisibili per 5. Questo riduce il numero di coppie possibili di un fattore di 200. D deve essere dispari usando considerazioni simili per il mod 4.
Il Mod 9 produce solo 4 biquadratici che producono 6 congruenze di interesse. Otterrai 1,7 miglioramenti da mod 9; 1.4 miglioramento da mod 13; 1,4 miglioramento da 29.
Se D e C hanno un fattore primo comune F allora ((A F) ^ 4 + (B F) ^ 4 può essere eliminato (è stato trattato prima). L'impatto è piccolo, ma aiuta, tuttavia.
Setacciare D ^ 4-C ^ 4 è meno efficiente, ma possiamo ancora fare certe cose. Per prima cosa, possiamo dividerlo per 625 prima della decomposizione.
Sia N il numero da scomporre. Il secondo vincolo è limitare A, B
// Ho copiato e incollato il resto dell'articolo. Non leggerlo se vuoi reinventare l'implementazione.
(defun constrained-search (L U)
"Find solution to A' + B' + C ' = D'
with L <= D < U."
(decompose-each (constraint-sieve L U)))
Questa funzione di primo passaggio vincolo-setaccia itera sulla variabile D sui valori tra L e
U che sono primi rispetto a 10. Per ogni D, itera sulla variabile C su valori inferiori a
D che sono nella corretta corrispondenza del modulo 625 con D. Quando una coppia (D, C) supera entrambi l'insieme di
test di modularità e test kctor e prime-factor comuni, quindi il valore N = (D '- C') / 625 è
mettere in una lista. Gli elenchi per ciascuna scelta di D vengono aggiunti insieme e restituiti come vdue del
funzione. Ecco il codice per la funzione first pass:
(defun constraint-sieve (L U)
"Applicare i vincoli modulari e dei fattori a D e C.
Restituisci la lista dei candidati che superano i test. "
(loop for D in (prime-10 L U)
append
(loop for C in (good-e-for-d D)
when (and (mod-ok-p D C)
(factor-ok-p D C))
collect
(/ (- (biquad D) (biquad C))
625))))
La funzione di secondo passaggio si decompone: ognuno prende l'elenco di candidati generato dal primo passaggio
come argomento. Si itera sulla variabile N sui candidati nell'elenco. Per ogni candidato, esso
calcola i limiti corretti su A e scorre tra di loro. Quando trova una A tale che N - A 'sia
un biquadrato, sfugge al livello esterno e restituisce alcune informazioni sul vincitore. Se un vincitore
si incontra, sarebbe necessaria un'altra funzione per identificarla completamente. Ecco il codice per il secondo
passa la funzione:
(defun decompose-each (candidates)
"Attempt to decompose each of the candidates.
Return successful decomposition."
(loop with hd-root = (biquad-rt 0.5)
for N in candidates
for a-limit = (i-biquad-rt N)
for a-min = (ceiling (* halflroot a-lim't))
do
(loop for A from a-min below a-limit
when (biquadrate-p (- N (biquad A)))
do
(return-from decompose-each (list N A))))))
Quanti candidati possiamo aspettarci che venga prodotto il primo passaggio?
Quanti valori A devono eseguire la scansione del secondo passaggio per il candidato medio? Supponiamo che il
i candidati sono distribuiti uniformemente sotto U ', quindi il limite superiore medio su A è circa 415. (U') '/' =
4U / 5 e solo il 16% di tale intervallo viene scansionato.