Está en la página 1de 30

Ingeniería Informática

I NTRODUCCIÓN A LA M ATEMÁTICA D ISCRETA


Notas sobre Aritmética entera

Índice 4.3. Igualdad de Bézout . . . . . . . . . . . . 17


4.4. Algotritmo Extendido de Euclides . . . . 19
1. Los números enteros 1 4.4.1. Versión elegante del AEE . . . . 21
1.1. Nuestros números . . . . . . . . . . . . . 1
1.2. Algunos enteros famosos . . . . . . . . . 2 5. Ecuación diofántica 22
1.3. División euclídea . . . . . . . . . . . . . 3 5.1. Algoritmos de resolución . . . . . . . . . 22
1.4. Funciones suelo y techo . . . . . . . . . 4 5.2. Reducción . . . . . . . . . . . . . . . . . 23
1.5. El resto: operador mod . . . . . . . . . . 4 5.3. Soluciones acotadas . . . . . . . . . . . . 24
1.6. El tamaño de los números . . . . . . . . 5
6. Primos 24
2. Algoritmos 5 6.1. Definición y primeras propiedades . . . 24
2.1. Requisitos . . . . . . . . . . . . . . . . . . 5 6.2. Factorización . . . . . . . . . . . . . . . . 25
2.2. Orden de un algoritmo . . . . . . . . . . 6 6.3. Contando primos . . . . . . . . . . . . . 25
2.3. Método de los invariantes . . . . . . . . 8 6.4. Dos problemas fundamentales . . . . . 26
6.5. Búsqueda de primos . . . . . . . . . . . 26
3. Un poco de Aritmética en binario 8 6.5.1. Criba de Eratóstenes . . . . . . . 26
3.1. La suma . . . . . . . . . . . . . . . . . . . 8 6.5.2. La criba en la primalidad y fac-
3.2. El producto . . . . . . . . . . . . . . . . . 11 torización . . . . . . . . . . . . . 27
3.3. Las potencias . . . . . . . . . . . . . . . . 12 6.5.3. Búsqueda de un primo de k bits 28
6.6. Búsqueda de divisores . . . . . . . . . . 28
4. Máximo común divisor. El Algoritmo de Eu- 6.6.1. Uso para primalidad y factori-
clides 15 zación . . . . . . . . . . . . . . . 29
4.1. El máximo común divisor . . . . . . . . 15 6.6.2. Factorización de Fermat . . . . . 30
4.2. Algoritmo de Euclides . . . . . . . . . . . 16
4.2.1. Análisis del Algoritmo de Euclides 16 7. Problemas sin resolver 30

1. Los números enteros


1.1. Nuestros números
En estas notas nos ocuparemos principalmente de los números enteros y sus propiedades.

Los principales conjuntos de enteros que estudiaremos son:


El conjunto de todos los enteros, que se designará por

Z = {. . . , −2, −1, 0, 1, 2, . . .}
El conjunto de todos los naturales o enteros no negativos, que se designará por

IN = {0, 1, 2, . . .}

El conjunto de todos los enteros positivos, que se designará por

Z+ = {1, 2, . . .}
También usaremos ocasionalmente otros cuerpos de números:
El conjunto de todos los racionales, que se designará por Q.

El conjunto de todos los reales, que se designará por R.

El conjunto de todos los complejos, que se designará por C.


Estas notas corresponden a los contenidos de la asignatura Introducción a la Matemática Discreta, correspondiente a los estudios de
Grado en Ingeniería Informática en la Universidad de Sevilla. Se incluyen muy pocas demostraciones.

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 primeros números de la sucesión de Fibonacci son

f 1 = 1, f 2 = 1, f 3 = 2, f 4 = 3, f 5 = 5, f 6 = 8, f 7 = 13, f 8 = 21, f 9 = 34, . . .

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

M 1 = 1, M 2 = 3, M 3 = 7, M 4 = 15, M 5 = 31, M 6 = 63, . . .

Algunas propiedades de estos números son:

• M n es un número cuya representación binaria consiste en n unos. ?


• M n no tiene que ser primo: de hecho, si n es compuesto entonces M n es compuesto. ?
• Solo se conocen 48 números primos de Mersenne; el mayor de ellos es M 57885161 = 257885161 − 1, un
número de más de diecisiete millones de cifras decimales.
n
Números de Fermat: Pierre de Fermat (1601-1665) definió los números de Fermat como F n = 22 +1, para
n ≥ 0. Un número primo de Fermat es un número de Fermat que es primo.
Los primeros números de Fermat son

F 0 = 3, F 1 = 5, F 2 = 17, F 3 = 257, F 4 = 65537, F 5 = 4294967297, F 6 = 18446744073709551617, . . .

Algunas propiedades de estos números 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)

Así, los primeros 4 números de Euclides son:


e1 = 2
e2 = 2 + 1 = 3
e3 = 2·3 + 1 = 7
e4 = 2·3·7 + 1 = 43

Algunas propiedades de estos números son:

• 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. ?

1.3. División euclídea


Es la división de enteros de toda la vida. Se llama así en honor de Euclides (325-265 AC):

Para cada par de enteros a ∈ Z, b ∈ Z+ existe un único par de enteros c, r con

a = c · b + r, 0≤r <b

entonces, c se llama el cociente y r el resto.

Si dividimos la igualdad anterior entre b tenemos la siguiente igualdad de fracciones:


a r r
=c+ , 0≤ <1
b b b
Gráficamente:
Si r > 0 (si r = 0, coinciden)

c ∈Z a
b = c + br c +1 ∈ Z

c es entonces el mayor entero menor o igual que a/b.

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:

b|a ⇐⇒ a = b · c (para algún c ∈ Z)

Primeras propiedades

En Z todo funciona como esperamos:


a ̸= 0, ab = 0 =⇒ b = 0 (no hay divisores de cero).

a ̸= 0, ab = ac =⇒ b = c (se verifica propiedad cancelativa).


Lo segundo es consecuencia directa de lo primero.
También se verifican las propiedades básicas siguientes:
a|b, b|c =⇒ a|c

a|b, c|d =⇒ ac|bd

Si m ̸= 0, a|b ⇐⇒ ma|mb

Si c divide a a 1 , a 2 , . . . , a n y m 1 , m 2 , . . . , m n ∈ Z, entonces c|(m 1 a 1 + m 2 a 2 + . . . + m n a n )

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).

⌈x⌉ = el menor entero mayor o igual que x (techo de x).

Ambas funciones están relacionadas por la propiedad reflexiva:

⌊−x⌋ = − ⌈x⌉ ; ⌈−x⌉ = − ⌊x⌋

Otra propiedad fundamental es

⌊x + n⌋ = ⌊x⌋ + n, ⌈x + n⌉ = ⌈x⌉ + n, para n entero.

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

Dos manipulaciones fundamentales:


¥ ¦
x < n < y ⇐⇒ ⌈x⌉ ≤ n ≤ y para x, y ∈ IR, n entero.

La misma propiedad se verifica si algún < es ≤:


¥ ¦
x ≤ n ≤ y =⇒ ⌈x⌉ ≤ n ≤ y para x, y ∈ IR, n entero.

1.5. El resto: operador mod


Si a y b son enteros positivos, definimos el operador mod como

a mod b = resto de dividir a entre b.

La igualdad de la división euclídea puede expresarse entonces del modo siguiente:


jak
a =b· + a mod b
b

En la división euclídea, ba = el cociente de dividir a entre b.


¥ ¦

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

Esto permite expresar a mod b como


a mod b = a − b ⌊a/b⌋
Esto permite la generalización a enteros negativos. Por ejemplo, si a = 369, b = −10, entonces el suelo de a/b =
−36, 9 es −37 y entonces
369 mod −10 = 369 − (−10) · (−37) = −1
IMPORTANTE: Muchas calculadoras (y otras implementaciones, como en Excel, por ejemplo) siempre hacen
a mod b positivo, lo que puede dar lugar a confusiones. Prueba en Excel la fórmula
= -10 * COCIENTE(365;-10) + RESIDUO(365; -10)
verás como no da 365.

1.6. El tamaño de los números


El tamaño de un número entero será el número de bits necesarios para expresarlo en binario.

Si la expresión binaria de n ≥ 0 es b k b k−1 . . . b 2 b 1 b 0 , donde cada b i es un bit y b k = 1, entonces


n = b k · 2k + b k−1 · 2k−1 + · · · + b 2 · 22 + b 1 · 2 + b 0
¥ ¦
y se tiene que k ≤ log2 n < k + 1 de donde k = log2 n y el número de bits de n es k + 1.

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:

Crecimiento 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

log n 4, 32 · 10−6 s 5, 32 · 10−6 s 5, 90 · 10−6 s

n 0, 00002 s 0, 00004 s 0, 00006s


n2 0, 0004 s 0, 0016s 0, 0036s
n3 0, 0008 s 0, 064 s 0, 216s

2n 1s 12, 7 días 36 558 años


34
n! 77 146 años 2, 58 · 10 años 2, 63 · 1068 años

Puede ser interesante comparar con la edad estimada del universo: (13, 7 ± 0, 2) · 109 años.

2.3. Método de los invariantes


El método de los invariantes guarda relación con una de las técnicas que se utiliza al depurar un fragmento de
código de un programa. Al depurar se define una expresión que debería mantenerse constante a lo largo de
toda la ejecución; si la expresión cambia de valor en alguna instrucción indica que ahí hay un error.

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.

Cada paso por el bucle lo deja sin cambios.

Al final se retorna al valor del invariante.

El esquema es como sigue:

Algoritmo para calcular x


x /* el valor que se retornará */
/* instrucciones de inicialización */
/* I 0 se evalúa a x */

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

/* El valor final de I , I f debe ser también x */


retorna x

Veremos cómo se hace en las secciones siguientes.

3. Un poco de Aritmética en binario


3.1. La suma
Nos planteamos ahora cómo sumar. La forma intuitiva (como hacen los niños que empiezan y también en
antiguas culturas primitivas) consiste en enumerar:

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) */

mientras (a > 0 ∥ b > 0) /* Recorre los bits de los sumandos */


si ((a&1) = (b&1)) /* 1+1, 0+0 */
si (m) s |=p /* s = s + m · p */
m = a&1
en otro caso /* 1+0, 0+1 */
si (!m) s |=p /* s = s + p */

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 */

Orden del algoritmo

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.

¿Funciona este algoritmo?

Usaremos el método de los invariantes para demostrar que el algoritmo retorna la suma de los números.

Veamos como se utiliza en el algoritmo. Consideramos el invariante I = (a + b + m) · p + s

9
Suma en binario
Entrada: a, b enteros positivos
Salida: a + b

m = 0 /* Acarreo: 'me llevo 1' (booleano: 1=verdadero, 0=falso */


s = 0 /* Suma parcial */
p = 1 /* Posición del siguiente bit a la izquierda (potencia de 2) */
I 0 = (a 0 + b 0 + m 0 ) · p 0 + s 0 = (a 0 + b 0 + 0) · 1 + 0 = a 0 + b 0
mientras (a > 0 ∥ b > 0) /* Recorre los bits de los sumandos */
I k = (a k + b k + m k ) · p k + s k
si ((a&1) = (b&1)) /* 1+1, 0+0 */
si (m) s| = p /* s = s + m · p */
m = a&1
en otro caso /* 1+0, 0+1 */
si (!m) s| = p /* s = s + p */

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 */

Al empezar I 0 = a · b (valores de entrada) y al terminar I f = m f · p f + s f , que es el valor retornado. Así basta


demostrar que I es un invariante, es decir que I k = I k+1 :

Vemos por separado los distintos casos que pueden darse en el bucle:

a k y b k tienen igual el bit menos significativo (1 + 1, 0 + 0).

• 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).

Hay dos subcasos:

• m k = 1 (me llevo 1): en este caso nada se cambia: I k+1 = I k .


• mk = 0
◦ s k+1 = s k + p k
◦ m k+1 = m k = 0
◦ a k+1 = (a k − 1)/2
◦ b k+1 = b k /2
◦ p k+1 = 2 · p k
Entonces
ak − 1 ak
µ ¶
I k+1 = + · 2p k + s k + p k = I k
2 2

10
3.2. El producto
La versión ingenua de la multiplicación consiste en sumas repetidas (yo lo he visto hacer así):

Algoritmo ingenuo para multiplicar


Entrada: a, b dos enteros positivos con a ≤ b
Salida: a · b
i =1
mientras (i ≤ b)
a+ = b
i ++

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:

Algoritmo para multiplicar


Entrada: a, b enteros positivos con a ≤ b
Salida: a · b
p = 0 /* el producto */

mientras (a > 0)
si (a es impar) p+ = b
b ≪= 1; /* b = 2 · b */
a ≫= 1; /* a = cociente de a/2 */

retorna p

Orden del algoritmo

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)).

¿Funciona este algoritmo?

Usaremos el método de los invariantes para demostrar que el algoritmo retorna el producto de los números.

Veamos como se utiliza en el algoritmo del producto; en el consideramos el invariante I k = p + a · b

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

Veamos el valor de I k+1 . Distinguiremos dos casos:

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.

3.3. Las potencias


Nos planteamos ahora cómo hacer una potencia b e con e grande.

El método evidente es hacer e multiplicaciones:

Algoritmo ingenuo para potencias


Entrada: b, e enteros positivos.
Salida: b e
p =1
repite e veces
p = p ·b
retorna p

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

Así solo hemos hecho 4 multiplicaciones (cuadrados y productos por la base).

Para lo anterior hemos aplicado tres reglas:

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

Algoritmo rápido para potencias


Entrada: b, e enteros positivos
Salida: b e
p =1
mientras e > 0
si e es impar
p = p · b // ← M
fin si
e ≫= 1 // e = ⌊e/2⌋
b = b 2 // ← C
fin mientras
retorna p

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

El algoritmo de las potencias rápidas es de orden O (log(e)).

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

Vamos a evaluar I k+1 considerando dos casos:

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

Entonces I es un invariante en todo el algoritmo, con lo que I f = I 0 ⇒ b f = b e y el algoritmo retorna b e .


¥q ¦
El bucle se ejecuta tantas veces como sea posible hacer la asignación q = 2 hasta tener q = 0, esto es el
número de bits del exponente m: el algoritmo es de orden O (log m).

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.

0.1. Expresamos el exponente en binario: 25 es 11001

0.2. Entre cada dos bits insertamos una C: 1C1C0C0C1

0.3. Sustituimos cada 1 por una M y eliminamos los 0: MCMCCCM

Ejecutamos ahora la secuencia obtenida empezando en 1 e interpretando las M y C como:

M significa “multiplica por la base”


C significa “eleva al cuadrado”

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

4. Máximo común divisor. El Algoritmo de Euclides


4.1. El máximo común divisor
Dados dos enteros a, b, no ambos nulos, se denomina máximo común divisor de a y b y se designa por mcd(a, b)
al mayor de sus divisores comunes, que existe y es único.

La propiedad fundamental del máximo común divisor d = mcd(a, b) es

d |a y d |b
Si c|a y c|b entonces c|d

Otras propiedades del máximo común divisor son:

mcd(a, b) = mcd(b, a) = mcd(−a, b) = mcd(a, −b) = mcd(−a, −b)

mcd(a, 1) = 1

mcd(a, a) = mcd(a, 0) = a

mcd(a 1 , a 2 , . . . , a k ) = mcd(a 1 , mcd(a 2 , . . . , a k ))

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

4.2. Algoritmo de Euclides


El algoritmo de Euclides para el cálculo del máximo común divisor es uno de los más antiguos documentados
y es también uno de los más elegantes y eficientes.
El algoritmo se basa en propiedad siguiente:

Si a = b · c + r es la división euclídea de a entre b, entonces mcd(a, b) = mcd(b, r )

Si se aplica este resultado recursivamente, obtenemos

mcd(a, b) = mcd(b, r 1 ) = mcd(r 1 , r 2 ) . . . = mcd(r n−2 , r n−1 ) = mcd(r n−1 , 0) = r n−1 = d

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 .

Esto se puede sistematizar en el siguiente algoritmo:

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

Por ejemplo, para a = 1492, b = 1066 obtenemos las sucesivas divisiones:

a = b · c + r
1492 = 1066 · 1 + 426
1066 = 426 · 2 + 214
426 = 214 · 1 + 212
214 = 212 · 1 + 2
212 = 2 · 106 + 0

y entonces mcd(1492, 1066) = 2

4.2.1. Análisis del Algoritmo de Euclides

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.

Fuerza bruta, examinando los divisores (lineal):

2256
≈ 3, 67 · 1063 años
106 · 60 · 60 · 24 · 365

Algoritmo de Euclides (logarítmico):

log2 2256 256


= = 0, 000256 segundos
106 106

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

La clave está en que si a = b · c + r es la división euclídea de a entre b, entonces

Div(a, b) = Div(b, r)

Si x es divisor de a y de b, entonces x es divisor de r = a − bc

Si x es divisor de b y de r , entonces x es divisor de a = bc + 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).

4.3. Igualdad de Bézout


Tomemos la tabla de divisiones realizadas por el algoritmo de Euclides para a = 1492, y b = 1066, donde obte-
nemos d = mcd(a, b) = 2:

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.

La igualdad obtenida antes es un caso de igualdad de Bézout:

Si d = mcd(a, b), existen enteros α, β con d = α · a + β · b

Los coeficientes α, β pueden ser positivos, negativos o cero.

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:

d = mcd(a, b) =⇒ ∃α, β ∈ Z tales que αa + βb = d

El recíproco es falso:
2 · 7 + (−1) · 5 = 9 ̸⇒ mcd(7, 5) = 9
Sin embargo con d = 1 es verdadero:

1 = mcd(a, b) ⇐⇒ ∃α, β ∈ Z tales que αa + βb = 1

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.

Una propiedad fundamental:

18
)
a ⊥b
=⇒ a|c
a | b ·c

4.4. Algotritmo Extendido de Euclides


Se puede modificar el algoritmo de Euclides para obtener la igualdad de Bézout:

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

// Ya hemos obtenido mcd (m, n) = a


retorna a

Vamos a extender el algoritmo para que nos calcule, además del mcd, los coeficientes de una igualdad de
Bézout.

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

Nuevas instrucciones aquí...


mientras b > 0
(a, b) = (b, a mod b) // Euclides
Nuevas instrucciones aquí...
fin mientras
// Ya hemos obtenido mcd (m, n) = a
Nuevas instrucciones aquí...
retorna a , α, β

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 , α, β

Un seguimiento de este algoritmo para a = 1492, b = 1066 nos da:

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

Igualdad de Bézout: (−5) · 1492 + (7) · 1066 = 2

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:

Algoritmo extendido de Euclides


Entrada: a, b enteros positivos
Salida: d = mcd(a, b) y α, β con α · a + β · b = d
r = b, ol d _r = a
s = 0, ol d _s = 1
t = 1, ol d _t = 0
mientras r > 0
c = ⌊ol d _r /r ⌋
// Exquisita simetría:
(ol d _r, r ) = (r, ol d _r − c · r )
(ol d _s, s) = (s, ol d _s − c · s)
(ol d _t , t ) = (t , ol d _t − c · t )
fin mientras
d = ol d _r, α = ol d _s, β = ol d _t
retorna (d , α, β)

Se puede demostrar que este algoritmo es correcto usando el invariante I = ol d _s · a + ol d _t · b − ol d _r , que


siempre vale cero.

Un seguimiento de este algoritmo para a = 1492, b = 1066 es el siguiente:

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

Obtenemos una Igualdad de Bézout: (−5) · (1492) + (7) · (1066) = 2

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).

5.1. Algoritmos de resolución


El resultado principal es

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.

Claramente si d no divide a c no hay soluciones: si existe una solución x 0 , y 0

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, y) = (x 0 + bλ, y 0 − aλ) con λ entero (1)

(x 0 + bλ, y 0 − aλ)

(b, −a)

(x 0 , y 0 )

Esto puede describirse como el siguiente algoritmo:

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

a(x 0 + bλ) + b(y 0 − aλ) = ax 0 + b y 0 + abλ − abλ = c ✓

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λ

Hay transformaciones que pueden realizarse sin perder soluciones.

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λ

De forma análoga se haría la reducción en la segunda.

5.3. Soluciones acotadas


Si las soluciones deben estar en ciertos intervalos se imponen las restricciones adecuadas en la solución gene-
ral.

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.

Algunas importantes propiedades son:

Si p es primo y a es un entero, entonces p|a ó p ⊥ a.

Si p es primo y a 1 , . . . , a k son enteros, entonces p|a 1 · . . . · a k =⇒ p divide a algún a i .


¥p ¦
Si n es compuesto, n es divisible por un primo menor o igual que n

Si p > 5 es primo entonces p = 6k ± 1 para algún entero k.

24
6.2. Factorización
Una sencilla pero importante propiedad es:

Todo entero mayor que 1 es divisible por un primo.

La demostración por inducción en n > 1 es inmediata:

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.

De hecho es sencillo demostrar que


¥p ¦
Todo entero compuesto es divisible por un primo menor o igual que n .
p
Si n = a · b, entonces uno de los dos a, b son ≤ ¥ n ya que si ambos fuesen mayores tendríamos
p p p p ¦
n = a · b > n · n = n. Si a ≤ ¥n entonces a ≤ n . Como a es divisible por algún primo p, ya
p ¦
tenemos que hay un primo p ≤ n que divide a n,

Del hecho de que todo entero es divisible por un primo se deduce:

Todo entero n > 1 es producto de primos:


m mk
n = p1 1 · . . . · pk
Si ordenamos los primos, p 1 < p 2 < . . . < p k , entonces esta descomposición es única.

La anterior es la llamada Descomposición de n en Factores Primos.

6.3. Contando primos


Hay infinitos primos.

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.

Si π(n) designa el número de primos menores o iguales que n, entonces

π(n)
lı́m =1
n→∞ n/ ln(n)

es decir, para n grande


n
π(n) ≈
ln n
Este resultado es conocido como el Teorema de los Números Primos.

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

108 5 761 455 5 428 681, 02


109 50 847 534 48 254 942, 43
1010 455 052 512 434 294 481, 90

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:

π(k bits): número de primos de k bits.

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.

k = 40 k = 64 k = 128 k = 256 k = 1024

π(k bits) 1, 93 · 1010 2, 05 · 1017 1, 90 · 1036 3, 25 · 1074 1, 27 · 10305


p(k impar) 0, 070 0, 044 0, 022 0, 011 0, 003
e(k impar) 14, 2 22, 5 44, 7 89, 1 355, 2

6.4. Dos problemas fundamentales


Los dos problemas más importantes relacionados con los números primos son:

Primalidad: decidir si un número es primo o compuesto.


Factorización: encontrar la descomposición en factores primos de un número.

El primer problema tendrá soluciones aceptablemente buenas. El segundo es otra cosa...

6.5. Búsqueda de primos


6.5.1. Criba de Eratóstenes

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.

Este algoritmo se puede describir como

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

Se puede demostrar que la complejidad de este algoritmo es O (n · log n · log log n)

6.5.2. La criba en la primalidad y factorización

La Criba de Eratóstenes es de hecho un método para resolver ambos problemas:

Dado un entero n:

0.1. Construimos la lista de primos menores o iguales que n

0.2. Si n aparece en la lista, es primo. FIN.

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

¿Cómo se encuentra un número primo de un tamaño determinado?

Si buscamos un primo de n bits podemos empezar construyendo un entero impar de n bits:


1 ’ ’ ··· ’ ’ 1
y ahora rellenamos cada bit ’ eligiéndolo al azar. Tenemos entonces un impar de n bits. Ahora probamos si
es primo: si lo es, ya lo tenemos. Si no es primo, volvemos a sortear.

Este método plantea dos preguntas:


0.1. ¿Cómo sabemos que ya hemos encontrado un primo?
La respuesta es: usando un test de primalidad. El problema es que el único test que tenemos es inviable
para números grandes.

0.2. ¿Cuántas veces tendremos que probar? ¿será un número inviable, o infinito? Recordando la tabla que
obtuvimos anteriormente:

π(k bits): número de primos de k bits


2k 2k−1

ln 2kln 2k−1
P (k bits): probabilidad de que al elegir al azar un entero impar de k bits, sea primo
π(k bits)
2k−2
E (k bits): número de intentos esperados para que eligiendo al azar un entero de k bits, sea primo
1
P (k bits

k = 40 k = 64 k = 128 k = 256 k = 1024

π(k bits) 1, 93 · 1010 2, 05 · 1017 1, 90 · 1036 3, 25 · 1074 1, 27 · 10305


p(k impar) 0, 070 0, 044 0, 022 0, 011 0, 003
e(k impar) 14, 2 22, 5 44, 7 89, 1 355, 2

Para n = 1024 la estimación es de 355 intentos hasta encontrar un primo.

El problema es que no sabemos cuándo lo hemos encontrado y hay que parar.

6.6. Búsqueda de divisores


Un método mejor que la Criba de Eratóstenes usa las propiedades estudiadas de los números primos: dado un
entero n se trata de encontrar el menor primo que lo divide. El algoritmo es el siguiente:

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:

10 790 283 070 806 014 188 970 529 años

6.6.1. Uso para primalidad y factorización

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.

Factorización mediante DivP


Entrada: n entero positivo
Salida: L lista de primos cuyo producto es n
L = ; // lista vacía
mientras n > 1
p = DivP(n)
añade p a L
n = n/p
fin mientras
retorna L

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.

7. Problemas sin resolver


Seguimos sin poder decidir si un entero es primo y sin saber factorizar: las soluciones que tenemos solo valen
para números pequeños

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

También podría gustarte