Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Z = {. . . , −2, −1, 0, 1, 2, . . .}
El conjunto de todos los naturales o enteros no negativos, que se designará por
IN = {0, 1, 2, . . .}
Z+ = {1, 2, . . .}
También usaremos ocasionalmente otros cuerpos de números:
El conjunto de todos los racionales, que se designará por Q.
1
1.2. Algunos enteros famosos
Mencionaremos aquí algunos números enteros que tienen propiedades notables y que utilizaremos a lo largo
del curso.
Indicaremos algunas de sus propiedades, por ahora sin demostración (más adelante demostraremos alguna
de ellas). De hecho, estas propiedades se enuncian utilizando conceptos que estudiaremos más tarde y usan
resultados que también estudiaremos posteriormente.
Números de Fibonacci: Leonardo de Pisa (1170-1250), también llamado Fibonacci definió la sucesión
infinita de enteros que lleva su nombre. En ella los dos primeros números son 1, 1 y cada uno de los
siguientes se obtiene sumando los dos anteriores.
Los números de Fibonacci tienen muchas propiedades como se verá a lo largo del curso. Algunas que
demostraremos después son:
• Dos números de Fibonacci consecutivos son primos entre sí: mcd( f n , f n+1 ) = 1. ?
• mcd( f n , f m ) = f mcd(n,m) ?
• f n puede ser calculado usando solo aritmética entera por un algoritmo de orden O (l og n).
• Una fórmula explícita para f n (que utiliza números reales y sorprendentemente se evalúa siempre
a un número entero) es à p !n à p !n
1 1+ 5 1 1− 5
fn = p −p
5 2 5 2
p
1+ 5
El número ϕ = 2 que aparece en esta fórmula recibe el nombre de razón áurea.
Números de Mersenne: Marin Mersenne (1588-1648) definió los llamados números de Mersenne como
M n = 2n − 1 para n ≥ 1. Un primo de Mersenne es un número de Mersenne que es primo.
Los primeros números de Mersenne son
• Los cinco primeros son primos; de hecho Fermat creía que todos eran primos. Euler probó que no
era así en 1732:
5
F 5 = 22 + 1 = 232 + 1 = 4294967297 = 641 · 6700417
• Actualmente, solo son conocidos cinco números primos de Fermat, que son los cinco primeros y
sólo se conoce la factorización completa de los doce primeros.
2
Números de Euclides: Los números de Euclides, llamados así en honor de Euclides (325-265 AC), se
definen de forma recursiva como
e1 = 2
e n = e 1 · e 2 · · · · · e n−1 + 1 (n > 1)
• Los cuatro primeros números de Euclides son primos; en cambio e 5 = 1807 = 13 · 139, con lo que no
todos lo son. No se sabe si existen infinitos números de Euclides que sean a su vez primos.
• Los numeros de Euclides son siempre primos entre sí dos a dos. ?
a = c · b + r, 0≤r <b
c ∈Z a
b = c + br c +1 ∈ Z
Si la división es exacta entonces r = 0 y se dice que b divide a a (o que b es un divisor de a, o que a es múltiplo
de b). Esta relación se designa mediante b|a:
Primeras propiedades
Si m ̸= 0, a|b ⇐⇒ ma|mb
3
1.4. Funciones suelo y techo
Para un número real x definimos las siguientes funciones:
⌊x⌋ = el mayor entero menor o igual que x (suelo o parte entera de x).
Si x es entero entonces
x ∈ Z ⇐⇒ x = ⌊x⌋ = ⌈x⌉
en otro caso podemos representar la situación de los tres valores sobre la recta real del modo siguiente:
⌊x⌋ ∈ Z x∉ Z ⌈x⌉ ∈ Z
Si a es múltiplo de b entonces
a jak lam a
b|a =⇒ ∈ Z =⇒ = =
b b b b
En otro caso podemos representar la situación de los tres valores sobre la recta real del modo siguiente:
∈Z Z ∈Z
¥a¦ a
§a¨
b b∉ b
Todo lo anterior supone divisiones con el divisor positivo. Las igualdades anteriores permiten generalizarlo a
positivos o negativos. La igualdad fundamental es
4
a = b · ⌊ a/b ⌋ + a mod b
cociente resto
Debe observarse que la división entera de un entero entre 2 consiste solamente en un deplazamiento de bits
De hecho existe un operador de desplazamiento de bits para expresar la division euclidea de un entero entre 2:
n ≫ 1 = ⌊n/2⌋
k−1
Esto se ve facilmente calculando ⌊n/2⌋ = b k · 2 + b k−1 · 2k−2 + · · · + b 2 · 2 + b 1 :
n = bk b k−1 b k−2 ... b1 b0
⌊n/2⌋ = bk b k−1 ... b2 b1
Como 2k ≤ n < 2k+1 , podemos representar los valores anteriores del modo siguiente:
20 21 22 2k n 2k+1
n n n
Si consideramos las divisiones euclídeas 2k
=1y 2k+1
= 0 podemos concluir que la asignación n = 2 puede
hacerse k + 1 veces hasta obtener cero.
Resumiendo:
¥ ¦
El número de bits de un número n es log2 n + 1 y es el número de veces que hay que dividir n entre 2 hasta
obtener cociente cero.
2. Algoritmos
En esta asignatura intentaremos que todas las técnicas que estudiemos se concreten de forma efectiva en al-
goritmos que permitan su ejecución en un programa de ordenador.
2.1. Requisitos
Estudiaremos ahora brevemente cómo debe ser un algoritmo. Para que un algoritmo sea bueno tiene que cum-
plir varias cosas:
Factible: todas sus instrucciones deben poderse realizar, y en el orden en que se especifican.
Finito: su proceso debe tener un final (técnica: acotaciones).
Efectivo: debe hacer lo que se desea (técnica: invariantes).
Eficiente: el orden de un algoritmo mide su eficiencia.
5
2.2. Orden de un algoritmo
Al medir la eficiencia de un algoritmo se utiliza el concepto de orden. Dicho de una forma simplificada, el orden
de un algoritmo mide el número de operaciones que realiza en función de n, el tamaño de sus entradas. Esta
medida vendrá dada por una función f (n). Para encontrar esta función siempre consideraremos el punto de
vista pesimista, es decir, si no sabemos si una operación se va a hacer, siempre supondremos que sí se hace.
Cuando tengamos una estimación de f (n) diremos que el algoritmo pertenece al orden O ( f (n)).
Según su orden un algoritmo será más o menos eficiente. Podemos observar cómo puede ser este crecimiento
viendo las gráficas de algunas funciones:
Los algoritmos de orden O (n k ) se dice que son polinomiales. Los de orden O (k n ) (con k > 1) se dicen exponen-
ciales.
Mucho más eficientes que los algoritmos lineales (O (n)) están los logarítmicos, de orden O (log n), como el
algoritmo de Euclides.
6
Función logarítmica, lineal y exponencial.
Debido a la escala, en la representación anterior, la función f (x) = log2 (x) parece casi una recta. Con una escala
mayor se ve que es mucho mejor:
Función logarítmica.
Debe observarse lo lentamente que crece log2 x aunque x sea muy grande.
Una tabla de tiempos puede ayudarnos a comparar los algoritmos para el mcd e ilustrar lo anterior. Si supo-
nemos que se hacen un millón de operaciones por segundo, vamos a calcular los tiempos de ejecución de
7
algoritmos de O ( f (n)) para ciertas funciones f y para algunos valores de n:
f (n) n = 20 n = 40 n = 60
Puede ser interesante comparar con la edad estimada del universo: (13, 7 ± 0, 2) · 109 años.
En el método de los invariantes para validar un bucle se define una expresión (el invariante), que:
Al principio del programa, tras la inicialización y antes de entrar en el bucle, toma el valor que se quiere
retornar.
mientras ( /* condición */ )
/* I k es el invariante evaluado justo al entrar en el paso k */
/* Instrucciones del bucle */
/* I k+1 es el invariante evaluado justo al salir del paso k */
/* I k+1 debe ser igual que I k */
fin del bucle
8
Algoritmo ingenuo para sumar
Entrada: a, b enteros positivos
Salida: a + b
mientras (b > 0)
a = a +1
b = b −1
retorna a
Es evidente que este algoritmo funciona, pero es de orden lineal O (n). Este orden es excesivo si n es grande,
por lo que necesitamos algo mejor. El mejor nos lo enseñaron en el colegio y se basa en la notación posicional
para los números.
Veamos un suma en binario similar al método que nos enseñaron en el colegio para sumar en decimal. Po-
demos expresarlo de una forma ingenua emulando el trabajo del escolar con lápiz y papel, que trabaja con
caracteres. Esto nos daría el siguiente algoritmo:
Suma en binario
Entrada: a, b enteros positivos
Salida: a + b
m = 0 /* Acarreo: 'me llevo 1.' Binario: verdadero=1, falso=0. */
s = 0 /* Suma parcial */
p = 1 /* Posición del siguiente bit a la izquierda (potencia de 2) */
a ≫= 1 /* a = cociente de a / 2 */
b ≫= 1 /* b = cociente de b / 2 */
p ≪= 1 /* p = 2 p */
retorna (m?s|p : s) /* m · p + s */
El bucle se ejecuta una vez para cada bit del mayor de los factores, con lo que el orden es logarítmico O (log(n)),
siendo n el mayor de los sumandos.
Usaremos el método de los invariantes para demostrar que el algoritmo retorna la suma de los números.
9
Suma en binario
Entrada: a, b enteros positivos
Salida: a + b
a ≫= 1 /* a = cociente de a / 2 */
b ≫= 1 /* b = cociente de b / 2 */
p ≪= 1 /* p = 2 p */
I k+1 = (a k+1 + b k+1 + m k+1 ) · p k+1 + s k+1
I f = (a f + b f + m f ) · p f + s f = m f · p f + s f
retorna (m?s|p : s) /* m · p + s */
Vemos por separado los distintos casos que pueden darse en el bucle:
• s k+1 = s k + m k · p k
• m k+1 = el bit menos significativo de a k y b k (son el mismo).
• a k+1 = (a k − m k+1 )/2
• b k+1 = (b k − m k+1 )/2
• p k+1 = 2 · p k
Entonces
a k − m k+1 b k − m k+1
µ ¶
I k+1 = + + m k+1 · 2p k + s k + m k p k = I k
2 2
a y b tienen distinto el bit menos significativo (1 + 0, 0 + 1). Como los dos casos se estudian de forma
simétrica, veremos en detalle el caso 1 + 0 (a k impar, b k par).
10
3.2. El producto
La versión ingenua de la multiplicación consiste en sumas repetidas (yo lo he visto hacer así):
retorna a
Claramente este algoritmo es lineal O (n). Esto es factible para productos pequeños (aunque más de factores
2, 3,... resulta incómodo. Par productos grandes es inviable. En nuestra ayuda viene lo que nos enseñaron en
el colegio. Usando las propiedades de la notación posicional, podemos encontrar un algoritmo mucho más
eficiente:
mientras (a > 0)
si (a es impar) p+ = b
b ≪= 1; /* b = 2 · b */
a ≫= 1; /* a = cociente de a/2 */
retorna p
Claramente el número de operaciones (sumas) que realiza este algoritmo es el número de bits 1 de a, en el peor
de los casos el número de bits de a. Asi el bucle se ejecuta una vez para cada bit del menor de los factores, con
lo que el orden es logarítmico O (log(n)).
Usaremos el método de los invariantes para demostrar que el algoritmo retorna el producto de los números.
11
Algoritmo para multiplicar
Entrada: a, b enteros positivos con a ≤ b
Salida: a · b
p = 0 /* el producto */
I 0 = 0 + a 0 · b 0 = a 0 · b 0 /* valores de entrada de a, b */
mientras (a > 0)
I k = p k + a k · b k /* valores de p, a, b al entrar en la iteración k */
si (a es impar) p = p + b
b = 2·b
a = ⌊a/2⌋
I k+1 = p k+1 + a k+1 · b k+1 /* valores de p, a, b al salir de la iteración k */
fin mientras
I f = p f + a f · b f /* valores de p, a, b antes de salir */
retorna p
Si a k es impar:
p k+1 = p k + b k
ja k a −1
k k
a k+1 = =
2 2
b k+1 = 2 · b k
Entonces
ak − 1
I k+1 = p k + b k + · 2 · bk = p k + ak bk = I k
2
Si a k es par:
p k+1 = p k
ja k a
k k
a k+1 = =
2 2
b k+1 = 2 · b k
Entonces
ak
I k+1 = p k + · 2 · bk = p k + ak bk = I k
2
Entonces I es un invariante en todo el algoritmo, con lo que I f = I 0 ⇒ b f = a · b y el algoritmo retorna a · b.
12
Este algoritmo hace evidentemente e multiplicaciones.
El problema es que si e es grande son muchas operaciones; sin embargo podemos mejorarlo.
Supongamos que queremos calcular 210 . Podemos hacerlo por el método ingenuo, haciendo 10 multiplicacio-
nes:
×2 ×2 ×2 ×2 ×2 ×2 ×2 ×2 ×2 ×2
1 −−→ 2 −−→ 4 −−→ 8 −−→ 16 −−→ 32 −−→ 64 −−→ 128 −−→ 256 −−→ 512 −−→ 1024
Pero también podemos tomar atajos:
22 = 4 ← Cuadrado
24 = (22 )2 = 16 ← Cuadrado
25 = 2 · 24 = 32 ← Multiplicación
210 = (25 )2 = 1024 ← Cuadrado
b1 = b
b 2r = (b r )2
b 2r +1 = b · b 2r
Estas reglas pueden aplicarse sistemáticamente usando para ello el siguiente algoritmo
El bucle de este algoritmo se ejecuta hasta que e = 0, y en cada paso del bucle e se divide por 2, así que el bucle
se ejecutará log2 (e). De este modo tenemos
Veamos que este algoritmo retorna efectivamente la potencia. b e . Para ello vamos a considerar el invariante
I = p · be
13
Algoritmo rápido para potencias
Entrada: b, e enteros positivos.
Salida: b e
p =1
I0 = p · be = 1 · be = be
mientras e > 0
e
I k = p k · b kk // k cuenta el número de la iteración
si e es impar, p = p · b
e = ⌊e/2⌋
b = b2
I k+1 = p k+1 · (b k+1 )e k+1
fin mientras
I f = p f · (b f )e f = p f · (b f )0 = p f // el subíndice f significa final
retorna p
Si e k es impar,
p k+1 = p k · b k
je k e −1
k k
e k+1 = =
2 2
2
b k+1 = b k
y entonces
e k −1
e b k
k+1
I k+1 = p k+1 · b k+1 = b k · b k · (e k2 ) 2 = b k ·
e
k · ek
−1
= Ik
Si e k es par,
p k+1 = p k
je k e
k k
e k+1 = =
2 2
e k+1 = (e k )2
y entonces
ek
I k+1 = p k+1 · (b k+1 )e k+1 = p k · (b k2 ) 2 = p k · bk ek = I k
Podemos dar una versión de este algoritmo con una regla fácil de recordar, adecuada para hacer potencias a
mano (se supone que con números no muy grandes). Lo mostramos sobre un ejemplo con exponente m = 25.
14
Por ejemplo para 225 se haría
M C M C C C M
1 −−−−−−→ 2 −−−−−−→ 4 −−−−−−→ 8 −−−−−−→ 64 −−−−−−→ 4096 −−−−−−→ 16777216 −−−−−−→ 33554432
Vamos a comparar los tiempos de ejecución para ambos algoritmos: supongamos que podemos hacer 106 =
1000000 de operaciones por segundo. Entonces el tiempo necesario, en segundos, sería el número de opera-
ciones dividido entre 106 . Veamos esto para distintas magnitudes del exponente:
m O (m) O (log m)
210 0, 001024 segundos 0, 000010 segundos
225 33, 55443 segundos 0, 000025 segundos
250 35, 70205 años 0, 000050 segundos
2100 4 · 1016 años 0, 000100 segundos
Es muy importante observar que el algoritmo rápido de potencias se puede adaptar fácilmente para calcular
cualquier potencia, aunque no se trate de elevar a una potencia números enteros sino otros objetos: matrices,
etc.
Es tambien interesante observar que cualquier sucesion MC que empiece por M se corresponde a un exponen-
te:
Exponente a partir de MC
Entrada: L lista MC empezando por M
Salida: entero e , exponente (en binario)
Se recorre L siguiendo los siguientes pasos:
si L termina en C se añade un 0 a L .
se reemplaza cada pareja CC por C 0C // un cero entre las C consecutivas
se eliminan las C
se reemplazan las M por unos.
retorna L // el exponente en binario
d |a y d |b
Si c|a y c|b entonces c|d
mcd(a, 1) = 1
mcd(a, a) = mcd(a, 0) = a
Un concepto relacionado con el de máximo común divisor es el del mínimo común múltiplo:
El mínimo común múltiplo de dos enteros positivos a, b es el menor de los múltiplos comunes de a y b y se
designa por mcm(a, b). La relación entre el mínimo común múltiplo y el máximo común divisor viene dada por
la igualdad
15
mcd(a, b) · mcm(a, b) = a · b
donde r 1 es el resto de dividir a entre b, r 2 es el resto de dividir b entre r 1 , y, en general, r k es el resto de dividir
r k−2 entre r k−1 .
Algoritmo de Euclides
Entrada: a, b enteros positivos
Salida: d = mcd(a, b)
mientras b > 0
(a, b) = (b, a mod b)
fin mientras
retorna a
a = b · c + r
1492 = 1066 · 1 + 426
1066 = 426 · 2 + 214
426 = 214 · 1 + 212
214 = 212 · 1 + 2
212 = 2 · 106 + 0
Finito
El Algoritmo es finito puesto que en cada iteración b decrece sin ser nunca negativo, con lo que ha de llegar a
ser cero.
Eficiente
Cada vez que se divide, el resto es mayor que 2 (hasta que es 1 y el algoritmo se acaba). Así el algoritmo
es de orden
O (log n)
siendo n el menor de los dos números.
A mediados del siglo XIX, Lamé demostró que el caso peor se da cuando se aplica a dos números de
Fibonacci consecutivos.
En 2002 Brigitte Vallée demostró que el número medio de divisiones que se realizan es
π2
log n
6
16
Podemos comparar los dos algoritmos que tenemos para calcular el mcd: vamos a suponen que queremos
calcular el mcd de dos números de 256 bits y que seguimos pudiendo hacer un millón de operaciones por
segundo.
2256
≈ 3, 67 · 1063 años
106 · 60 · 60 · 24 · 365
Correcto
Para ver que es correcto usamos el método de los invariantes:
Algoritmo de Euclides
Entrada: a, b enteros positivos
Salida: d = mcd(a, b)
k = 0 // Contador de pasos por el bucle
// El invariante será I = mcd(a, b)
// ak , bk son los valores de a, b en el paso k
// Los valores de entrada son a0 , b0
// El mcd que se quiere calcular es I 0 :
I 0 = mcd(a 0 , b 0 )
mientras b > 0
// ak , bk son los valores de a, b en este momento
(a, b) = (b, a mod b)
// ak+1 , bk+1 son los valores de a, b en este momento
I k+1 = mcd(a k+1 , b k+1 )
k = k +1
fin mientras
// a f , b f son los valores de a, b al salir del bucle
I f = mcd(a f , b f ) // ahora b f = 0 y I f = a f
retorna a
Div(a, b) = Div(b, r)
Entonces, en el algoritmo
I f = mcd(a f , b f ) = mcd(a f , 0) = a f
Así el valor retornado es a f = I f = I 0 = mcd(a, b) (los valores de entrada).
17
1492 = 1 · 1066 + 426
1066 = 2 · 426 + 214
426 = 1 · 214 + 212
214 = 1 · 212 + 2
212 = 106 · 2 + 0
Si reescribimos esta tabla poniendo 1492 = a, 1066 = b, 2 = d y llamando r 1 , r 2 , r 3 a los restos, tenemos:
a = b + r1 (1)
b = 2 · r1 + r2 (2)
r1 = r2 + r3 (3)
r2 = r3 + d (4)
Ahora despejamos d de la última igualdad y eliminamos los restos r 3 , r 2 , r 1 usando las igualdades anteriores
(de abajo hacia arriba), con lo que expresamos d como combinación lineal de a y b:
d = r2 − r3 = por (4).
= r 2 − (r 1 − r 2 ) = −r 1 + 2r 2 = por (3): ya no hay r 3 .
= −r 1 + 2(b − 2r 1 ) = 2b − 5r 1 = por (2): ya no hay r 3 ni r 2 .
= 2b − 5(a − b) = por (1): ya no hay restos.
= −5a + 7b
Es claro que este procedimiento puede seguirse para cualquier par de enteros a, b.
El procedimiento anterior siempre obtendrá la misma igualdad, pero esto no significa que los coeficien-
tes de la igualdad de Bézout sean únicos; de hecho hay infinitas formas de expresar d como combinación
lineal de a y b:
d = αa + βb ⇒ d = (α + bk) a + (β − ak) b (∀k ∈ Z)
αk βk
Primos relativos
La igualdad de Bézout afirma que d = mcd(a, b) puede ponerse como combinación lineal de a y b:
El recíproco es falso:
2 · 7 + (−1) · 5 = 9 ̸⇒ mcd(7, 5) = 9
Sin embargo con d = 1 es verdadero:
Dos enteros a, b se dice que son primos relativos (o primos entre sí) si mcd(a, b) = 1.
Esta relación se designa como a ⊥ b:
a⊥b ⇐⇒ mcd(a, b) = 1
Nótese que dos números primos entre sí no necesitan ser primos.
18
)
a ⊥b
=⇒ a|c
a | b ·c
Algoritmo de Euclides
Entrada: m, n enteros positivos
Salida: mcd(m, n)
a = m, b = n // para no alterar los valores de entrada
mientras b > 0
(a, b) = (b, a mod b) // Euclides
fin mientras
Vamos a extender el algoritmo para que nos calcule, además del mcd, los coeficientes de una igualdad de
Bézout.
Añadimos las instrucciones necesarias para calcular, a la vez que el mcd, los coeficientes de una igualdad de
Bézout. Se resaltan en color rojo:
19
Algoritmo extendido de Euclides
Entrada: m, n enteros positivos
Salida: mcd(m, n) y α, β con α · m + β · n = mcd(m, n)
a = m, b = n // para no alterar los valores de entrada
s = 1 // signo
// Se utiliza una matriz M 2 × 2 que al final servirá para calcular
// los coeficientes de la igualdad de Bézout.
// La matriz se inicializa a la matriz unidad:
m 11 = 1, m 12 = 0, m 21 = 0, m 22 = 1
mientras b > 0
c = a/b, r = a − c · b
a = b, b = r // Euclides
µ ¶
c 1
// la matriz M se multiplica por la matriz
1 1
t 11 = m 11 · c + m 12 , t 12 = m 11 , t 21 = m 21 · c + m 22 , t 22 = m 21
m 11 = t 11 , m 12 = t 12 , m 21 = t 21 , m 22 = t 22
s = −s
fin mientras
// Ya hemos obtenido mcd (m, n) = a
// y los coeficientes de una igualdad de Bézout:
α = s · m 22 , β = −s · m 12
retorna a , α, β
k a b c r m 11 m 12 m 21 m 22 s
0 1492 = a 1066 = b 1 0 0 1 1
1 1066 426 1 426 1 1 1 0 −1
2 426 214 2 214 3 1 2 1 1
3 214 212 1 212 4 3 3 2 −1
4 212 2 1 2 7 4 5 3 1
5 2=d 0 106 0 746 7=β 533 5 = −α −1
20
4.4.1. Versión elegante del AEE
El Algoritmo extendido de Euclides se puede expresar de una forma más elegante y demostrar su corrección
mediante el uso de un invariante que se demuestra que iempre vale cero:
k ol d _r r ol d _s s ol d _t t I = ol d _s · a + ol d _t · b − ol d _r
0 1492 = a 1066 = b 1 0 0 1 (1) · 1492 + (0) · 1066 − 1492 = 0
1 1066 426 0 1 1 −1 (0) · 1492 + (1) · 1066 − 1066 = 0
2 426 214 1 −2 −1 3 (1) · 1492 + (−1) · 1066 − 426 = 0
3 214 212 −2 3 3 −4 (−2) · 1492 + (3) · 1066 − 214 = 0
4 212 2 3 −5 −4 7 (3) · 1492 + (−4) · 1066 − 212 = 0
5 2=d 0 −5 = α 533 7=β −746 (−5) · (1492) + (7) · (1066) − 2 = 0
Las tablas de seguimiento de estos dos algoritmos pueden servir como método para calcular una igualdad de
Bézout cuando se hace a mano, con solo una calculadora, pero este método es desaconsejado: como método
para calcular una igualdad de Bézout sin ordenador, es más sencillo y mucho menos propenso a errores el
descrito en una sección anterior.
21
5. Ecuación diofántica
Una ecuación diofántica lineal con dos incógnitas (para nosotros, simplemente ecuación diofántica), es una
ecuación
a ·x +b · y = c
donde a y b son enteros distintos ce cero, c es un entero cualquiera y buscamos solo las soluciones enteras
(positivas, negativas o nulas).
La ecuación diofántica ax + b y = c tiene solución si y sólo si d = mcd(a, b) divide a c, y entonces tiene infinitas
soluciones.
d |a, d |b ⇒ d |(ax 0 + b y 0 ) ⇒ d |c
La demostración de que si d |c hay infinitas soluciones aporta de hecho un método constructivo para resolver
la ecuación.
En efecto, como d divide a a y a b, si hay solución (x 0 , y 0 ) entonces d |(ax 0 + b y 0 ) = c. Además, en este caso, la
igualdad de Bézout αa + βb = d nos da una solución particular (x 0 , y 0 ):
c c c
αa + βb = d =⇒ a · α +b · β =
d
d d d
x0 y0
A partir de esta solución particular podemos obtener todas las soluciones: si (x, y) es una solución, entonces
ax + b y = ax 0 + b y 0 y de aquí
a b
ax − ax 0 = b y 0 − b y =⇒ a(x − x 0 ) = b(y 0 − y) =⇒ (x − x 0 ) = (y 0 − y) =⇒ a ′ |b ′ (y 0 − y)
d d
a′ b′
Como αa ′ + βb ′ = 1 es a ′ ⊥ b ′ y por tanto a ′ |(y 0 − y), es decir existe un entero k tal que y 0 − y = a ′ k de donde
y = y 0 − a ′ k = β dc − da k. Si ahora sustituimos este valor de y en ax + b y = c, obtenemos que x = α dc + db k.
Resumiendo estos resultados tenemos un procedimiento de resolución mediante un algoritmo paso a paso:
Operación Obtenemos
1 d = mcd(a, b) d
2 Si d ̸ |c no hay solución FIN
3 Dividimos entre d : a = a/d , b = b/d , c = c/d ax + b y = c
4 Una igualdad de Bézout para (los nuevos) a, b αa + βb = 1
5 Multiplicamos por c (αc)a + (βc)b = c
6 Tenemos una solución particular x 0 = αc, y 0 = βc
7 Sumamos y restamos ±|ab|λ αac + abλ + βbc − abλ = c
8 Sacamos factor común a y b (αc + bλ)a + (βc − aλ)b = c
9 Una solución general es x = αc + bλ, y = βc − aλ
Es posible demostrar que el algoritmo anterior obtiene todas las soluciones, pero esto lo haremos desde otro
punto de vista.
22
Algoritmo simplificado de resolución
Se puede usar también una versión simplificada del algoritmo de resolución, basado en una idea geométrica:
en el plano IR2 , la ecuación ax + b y = c representa una recta de vector dirección (b, −a). Las soluciones de la
correspondiente ecuación diofántica son los puntos de esa recta que tienen coordenadas enteras. Además si
mcd(a, b) = 1 y (x 0 , y 0 ) es un punto de la recta con coordenadas enteras (una solución particular de la ecuación
diofántica), entonces todas las soluciones de la ecuación se obtienen con la expresión parametrizada
(x 0 + bλ, y 0 − aλ)
(b, −a)
(x 0 , y 0 )
Operación Obtenemos
1 Una igualdad de Bézout para a, b αa + βb = d
2 Si d ̸ |c no hay solución FIN
3 Dividimos entre d : a = a/d , b = b/d , c = c/d αa + βb = 1
4 Una solución general es x = αc + bλ, y = βc − aλ
Ahora es fácil demostrar que el algoritmo obtiene todas las soluciones y sólo las soluciones.
Cualquier punto de la forma (1) es una solución: basta sustituir en la ecuación diofántica
Todas las soluciones son de la forma (1): si (x, y) es una solución, entonces por ser puntos de la recta existe
un número real λ tal que (x − x 0 , y − y 0 ) = λ(b, −a). Veamos que λ es un entero. x − x 0 = bλ por lo que λ
es una fracción, λ = x−x n
b . Podemos reducir esta fracción obteniendo λ = m con n y m primos entre sí y
0
m > 0; así
n
x = x0 + b ⇒ m divide a b.
m
n
y = y 0 − a ⇒ m divide a a.
m
Así m divide a mcd(a, b) = 1, de donde m = 1 y entonces λ es un entero y la solución es de la forma
(1) ✓
5.2. Reducción
A menudo el algoritmo de resolución da soluciones con números grandes que algunas veces pueden simplifi-
carse. Por ejemplo si la solución paramétrica obtenida es
¾
x = x 0 + bλ
y = y 0 − aλ
23
0.1. La más sencilla es innecesaria si se ha aplicado el algoritmo de resolución descrito antes. Consiste en
dividir los coeficientes b, a por d = mcd(a, b).
0.2. Una transformación que a veces es interesante es hacer positivo algún coeficiente del parámetro, hacien-
do la sustitución λ → −λ.
0.3. También podemos reducir el término independiente de cualquiera de las igualdades de la solución ge-
neral mediante una simple traslación λ → λ− q. Por ejemplo, si queremos reducir la primera igualdad en
la solución paramétrica anterior, hacemos primero b positivo y mediante la división euclídea de x 0 entre
b y obtenemos el cociente q y el resto r :
r = x 0 mod b
x0 − r
q =
b
y entonces hacemos la sustitución
λ → λ−q
con lo que las dos ecuaciones paramétricas de la solución quedan
¾
x = r + bλ
y = (y 0 + aq) − aλ
Por ejemplo, en un cajero que dispensa billetes no sirven las soluciones negativas, por lo que tendríamos las
inecuaciones:
x = αc + bλ ≥ 0
¾
y = βc − aλ ≥ 0
y buscamos valores para λ que verifiquen ambas condiciones.
Nótese que puede ocurrir que aunque un sistema general tenga infinitas soluciones, puede que con las restric-
ciones no haya soluciones, que haya una sola o que sean una cantidad finita.
6. Primos
6.1. Definición y primeras propiedades
Un entero p > 1 es primo si sus únicos divisores positivos son 1 y p. Un entero positivo que no es primo se dice
compuesto.
Nótese la diferencia entre el que un número sea primo y que dos números sean primos entre sí: los segundos
pueden no ser primos.
24
6.2. Factorización
Una sencilla pero importante propiedad es:
El caso inicial es n = 2, que es divisible por él mismo. Si lo suponemos para todo entero menor que
n entonces es cierto para n: si n es primo, ya está; si no, n es compuesto, n = a · b con 1 < a < n y
por hipótesis de inducción a es divisible por un primo p y entonces p|n.
Euclides demostró este hecho© de un modo ªelegante, por reducción al absurdo: si el conjunto de
todos los primos fuese finito p 1 , p 2 , . . . , p m entonces el número n = p 1 · p 2 · . . . · p m + 1 no sería
divisible por ningún primo.
π(n)
lı́m =1
n→∞ n/ ln(n)
25
n
Podemos ver cómo el valor ln n aproxima a π(n):
n π(n) n/ ln(n)
10 4 4, 34
102 25 21, 71
103 168 144, 76
4
10 1 229 1 085, 74
105 9 592 8 685, 89
6
10 78 498 72 382, 41
107 664 579 620 420, 69
Podemos hacer también una estimación acerca del número de primos de k bits: el número de primos de k bits
o menos es
2k 2k
=
ln(2k ) k ln 2
Entonces, de k bits habría
2k 2k−1 (k − 2) · 2k−1
− =
k ln 2 (k − 1) ln 2 k · (k − 1) · ln 2
Podemos ver algunos valores concretos:
p(k impar): probabilidad de que al elegir al azar un entero impar de k bits, sea primo.
e(k impar): número de intentos esperados para que eligiendo al azar un entero impar de k bits, sea primo.
El único primo par es 2. Los números primos menores que 20 son 2, 3, 5, 7, 11, 13, 17 y 19.
Eratóstenes (276-194 AC) propuso el método que lleva su nombre para generar todos los primos menores que
un entero n dado:
26
0.1. Se listan todos los números desde 2 hasta n.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...
¥p ¦ número p = 2 no es divisible por ningún primo anterior (no los hay) luego es primo; entonces si
0.2. El primer
p > n , se detiene el proceso y todos los elementos que quedan en la lista son primos. Si no, se borran
todos los siguientes que sean múltiplos de p:
2 3 5 7 9 11 13 15 17 19 ...
0.3. Como el siguiente entero p = 3 no¥ puede tener divisores primos anteriores (si no, estaría borrado), él
p ¦
mismo es primo; entonces si p > n , se detiene el proceso y todos los elementos que quedan en la
lista son primos. Si no, se borran todos los siguientes que sean múltiplos de p:
2 3 5 7 11 13 17 19 ...
0.4. Como el siguiente entero p = 5 no¥ puede tener divisores primos anteriores (si no, estaría borrado), él
p ¦
mismo es primo; entonces si p > n , se detiene el proceso y todos los elementos que quedan en la
lista son primos (si n fuese 20, el proceso se detendría aquí). En otro caso, se borran todos los siguientes
que sean múltiplos de p.
2 3 5 7 11 13 17 19 ...
¥p ¦
0.5. Así sucesivamente hasta que p, el primer elemento de la lista sea mayor que n y entonces todos los
elementos que quedan en la lista son primos.
C RIBA DE E RATÓSTENES
entrada: n entero mayor que 1
salida: lista de todos los primos menores o iguales que n
l n = lista ordenada de todos los enteros k con 2 ≤ k ≤ n
l p = lista vacía
mientras l n no esté vacía
p = primer elemento de l n
si p 2 > n
añade a l p todos los elementos de l n y vacia l n
en otro caso
añade p a l p y quita de l n todos los múltiplos de p
retorna l p
Dado un entero n:
0.3. Si n no aparece en la lista, sus divisores primos están en la lista de primos que hemos construido.
Ésta no es una buena solución ya que es es un algoritmo polinomial, que no sirve para enteros grandes.
27
6.5.3. Búsqueda de un primo de k bits
0.2. ¿Cuántas veces tendremos que probar? ¿será un número inviable, o infinito? Recordando la tabla que
obtuvimos anteriormente:
DivP
Entrada: n entero positivo
Salida: el menor primo divisor de n
si 2|n retorna 2
k 3
si 3|nj pretorna
n−1
m= 6
para k = 1 hasta m
si 6k − 1|n retorna 6k − 1
si 6k + 1|n retorna 6k + 1
fin para
retorna n
28
0.1. Este algoritmo siempre retorna el menor primo divisor de n.
Distinguimos dos casos:
Si n es un primo p entonces nunca se dan las condiciones de salida de dentro del bucle y se retorna
p, el menor primo que divide a n.
Si n es compuesto y p es el menor primo que divide a n entonces:
• Si p = 2 o p = 3 se sale sin entrar en el bucle y se retorna p.
p
j p dek los dos es p = 6k + 1. También p ≤ n de donde
• Si p > 3 entonces p = 6k ± 1 y el mayor
p p n−1
6k+ ≤ n =⇒ 6k ≤ n − 1 =⇒ k ≤ 6 = m (notación del algoritmo). Entonces el bucle
llega a p y lo retorna.
1
0.2. El número de operaciones que hace el algoritmo es del orden O (n 2 ).
En efecto, antes del bucle se hacen una raíz cuadrada y tres divisiones. En cada iteración se hacen dos
divisiones y en eljcaso
p k desfavorable (n primo) el bucle se ejecuta m veces. Así el número de divisiones
más
1
n−1
es 4 + 2m = 4 + 2 6 ∈ O (n 2 ).
¿Cuánto tiempo podría llegar a tardar este algoritmo en encontrar un factor primo de n si n tuviera tuviera
1
256 bits? Como el algoritmo de de orden O (n 2 ), si n ≃ 2256 entonces el número de operaciones es del orden
1 1
(2 )256 2
O ((2256 ) 2 ). Haciendo 1000000 de operaciones por segundo, esto supondría aproximadamente 1000000 ≃ 34·1031
segundos y dividiendo este número de segundos entre 60·60·24·365 tendríamos una aproximación del número
de años:
Primalidad: el algoritmo DivP(o cualquier otro que encuentre un divisor primo) puede ser usado
como un test de primalidad: si el valor retornado p es igual a su entrada n es que n es primo.
Este test es determinista, ya que su respuesta es siempre segura.
Factorización: si aplicamos el algoritmo a un entero n 1 = n encontramos p, un factor primo de n.
n
Si a continuación lo aplicamos a n 2 = pi encontramos otro (puede que el mismo) y así suce-
sivamente, hasta que n i = 1 (o sea primo) y entonces tenemos todos los factores primos de
n. Por tanto, el algoritmo anterior puede usarse para encontrar la factorización de cualquier
número (lo llamaremos factorización por fuerza bruta.
Ya hemos visto que este algoritmo no es viable para enteros grandes. Podemos mejorarlo un poco combinán-
dolo con el uso previo de una tabla precalculada de los primeros primos (Eratóstenes). Con esa tabla se buscan
divisores primos pequeños del número y luego se aplica el algoritmo anterior (modificado para no repetir las
divisiones anteriores).
SI tuvieramos un buen test de primalidad podríamos mejorar el algoritmo de fuerza bruta para obtener la fac-
torización: en cada paso comprobaríamos si el n que nos queda ya es primo (con lo que habríamos terminado).
29
6.6.2. Factorización de Fermat
En 1643 Mersenne desafió a Fermat a que éste factorizara el número 2027651281. Fermat contestó rápidamente
2027651281 = 44021 · 46061. ¿Cómo lo hizo?
La idea de Fermat consiste en que, dado n impar, si encontramos x, y tales que n = x 2 − y 2 tendremos n =
(x + y)(x − y). Si ninguno de estos factores es 1, ya hemos encontrado dos divisores propios de n. El método
p
consiste entonces en probar todos los x > n hasta que x 2 − n sea cuadrado perfecto.
Esto se puede sistematizar en el siguiente algoritmo
Factorización de Fermat
Entrada: n positivo impar
Salida: un factor de n
§p ¨
x = (n)
yC = x 2 − n // yC = candidato a y 2
mientras yC no sea un cuadrado
x = x +1
yC = x 2 − n
fin mientras
p
retorna x − yC
Si n tiene más de dos factores primos, este procedimiento primero encuentra la descomposición con el menor
p n
valor de x e y. Es decir, x + y es el menor factor mayor o igual que n. Por tanto, x − y = x+y es el mayor factor
p
menor o igual que n. Si el procedimiento devuelve n = 1 · n, entonces n debe ser primo.
Si n es primo hacen falta O (n) pasos. Esta es desde luego una mala forma de demostrar la primalidad de un nú-
mero. Pero si n tiene un factor próximo a su raíz cuadrada, el método funciona rápidamente. Concretamente,
p
si n tiene un factor que difiere de n en menos de (4n)1/4 , entonces el método sólo necesita un paso, y esto es
independiente del tamaño de n.
En su forma más simple, el método de Fermat puede ser incluso más lento que el de fuerza bruta, en el peor de
los casos. Sin embargo, la combinación de ambos es más efectivo que el uso exclusivo de uno de ellos.
Está claro que un gran problema en todo lo visto es que no tenemos un test eficiente para decidir si un entero
es primo o no. Las buenas noticias son que pronto estudiaremos alguno.
30