El método de resolución utilizado es sencillo, consiste en generar todas
las fracciones con denominador menor o igual que n, y entre ellas seleccionar las irreducibles
(fuerza bruta).
Para generar todas las fracciones basta con dos bucles for anidados, uno
designando el numerador y otro el denominador. La dificultad del problema está en ver si una
fracción es irreducible o no. Para esto hay varios métodos:
1.- Ver si hay algún número entre 2 y el denominador que sea divisor a la vez del
numerador y del denominador, con lo que el tiempo de ejecución sería de O(n3). Una
mejora a este método sería mirar sólo los números primos entre 2 y el denominador, con lo que
habría que generar una tabla con los números primos menores que N. Como el número de primos
menores que N es casi proporcional a N (más o menos una décima parte), el tiempo de ejecución
sigue siendo de O(n3).
2.- El método utilizado para resolver el problema tiene tiempo casi constante.
El método se basa en que una fracción es irreducible si el numerador y el denominador son primos
entre sí, esto es, el máximo común divisor (MCD) del numerador y el denominador es 1. Ahora, para
hallar el MCD de dos números se puede utilizar el algoritmo de Euclides, que se basa en que si:
a = b*q + r , donde q = floor(a/b), y r = a mod b = a%b
entonces:
MCD(a,b) = MCD(b,r)
Tanto b como r son más pequeños que a, con lo que tendríamos el mismo problema con dos números más
pequeños. Si se aplica este método sucesivamente:
a = b*q1 + r1
b = r1*q2 + r2
r1 = r2*q3 + r3
r2 = r3*q4 + r4
...
rn-2 = rn-1*qn + rn
rn-1 = rn*qn+1 + 0
llega un momento en el que la división es exacta. Al llegar a ese instante, se sabe que:
MCD(rn-1,rn) = rn
pero como:
MCD(rn-1,rn) = MCD(rn-2,rn-1)
aplicando esto sucesivamente se tiene que:
rn = MCD(rn-1,rn) = MCD(rn-2,rn-1) = MCD(rn-3,rn-2)
= ... = MCD(r2,r3) = MCD(r1,r2) = MCD(b,r1) = MCD(a,b)
esto es,
rn = MCD(a,b)
Por ejemplo, para hallar el MCD de 75 y 20, los pasos a dar serían:
75 = 20*3 + 15
20 = 15*1 + 5
15 = 5*3 + 0
por lo que MCD(75,20) = 20.
Este método para hallar el MCD de dos número utiliza un número de iteraciones muy pequeño, casi
despreciable frente a n, por lo que el tiempo de ejecución utilizando este método sería de O(n2).
Lo único que queda hacer es ordenar las fracciones. Para
ello utilizamos la función qsort implementada ya en C (en stdlib.h),
que tiene un tiempo de ejecución de O(n*log(n)), despreciable frente
al tiempo de ejecución del programa entero. Sólo queda crear la
función de comparación, último argumento de la función
qsort. Para ello se puede utilizar el valor con decimales de la función,
pero si no se quiere utilizar números reales basta con fijarse en que:
a/b > c/d <=> a*d > c*b <=> a*d
- c*b > 0 (por ser a,b,c y d positivos)
a/b = c/d <=> a*d = c*b <=> a*d
- c*b = 0
a/b < c/d <=> a*d < c*b <=> a*d
- c*b < 0 (por ser a,b,c y d positivos)
con lo que la función sólo tendría que devolver el número
a*d - c*b. La función de comparación:
int compar(const void *A,const void *B)
del qsort tiene que devolver un valor menor que 0 si AB, y 0 si A=B.
Temas relacionados
Algoritmos de ordenación
Código Código fuente en C Código fuente en Pascal |