sto facendo la soluzione per questo problema da Euler Project Problem 513, Integral median:Come ottimizzare il mio codice per trovare il conteggio di tutte le mediane integrali per tutti i possibili triangoli integrali con un <= b <= c <= 100000?
ABC è un triangolo con i lati lati integrale a≤b≤c. mc è la mediana che collega C e il punto medio di AB. F (n) è il numero di tali triangoli con c≤n per cui mc ha anche lunghezza integrale. F (10) = 3 e F (50) = 165.
Trova F (100000).
Analyse:
a <= b <= c <= n == 100000
- ABC è un triangolo così dovrebbe:
abs(a-b) < c < a+b
Mc = sqrt(2 * a^2+ 2 * b^2 - c^2)/2
wikipediaMc
è intero così2 * a^2+ 2 * b^2 - c^2
dovrebbe essere un quadrato perfetto e divisibile per 4.
Codice:
#include <stdio.h>
#include <math.h>
#define N 100000
#define MAX(a,b) (((a)>(b))?(a):(b))
void main(){
unsigned long int count = 0;
unsigned long int a,b,c;
double mc;
for (a = 1; a <= N; a++) {
printf("%lu\n", a);
for (b = a; b <= N; b++)
for (c = MAX(b, abs(b-a)); c <=N && c < a+b; c++){
mc = sqrt(2 *a *a + 2 * b * b - c * c)/2.0;
if (mc-(unsigned long)mc == 0)
count++;
}
}
printf("\ncpt == %lu\n", count);
}
Issues:
Funziona bene per le piccole n
ma la complessità della soluzione è troppo alto, suppongo che sia O(n^3)
(mi sbaglio?) che impiegherà giorni per n = 100000
.
Come potrei migliorare questo con un metodo matematico o algoritmico?
Aggiornamenti
ho avuto questi suggerimenti:
- Calcolo potere dei
a
al di fuori deib
/c
loop e la potenza dib
fuoric
ciclo. Questo ha migliorato leggermente le prestazioni. c
non può essere dispari. quindia
eb
devono avere la stessa parità. Questo ha migliorato le prestazioni 4 volte.- Utilizzo di thread per dividere il lavoro su molti core. Può migliorare di un fattore vicino al numero di core.
- Una soluzione matematica pubblicata in math.stackexchange. Si richiede
O(N^5/2)
per una soluzione di base e può raggiungereO(N^2)
utilizzandoO(N^2)
di memoria. Non l'ho ancora testato.
Per i principianti, è possibile calcolare '2 * a * a' prima del ciclo' b', e '2 * a * a + 2 * b * b' prima del ciclo' c'. –
Dal n. 4, 'c' non può essere dispari. quindi 'a' e' b' devono avere la stessa parità. Non è una soluzione completa, ma dovrebbe darti un fattore di miglioramento 4. – SleuthEye
Perché non è 'for (c = b; c <= N; C++)'? –