Escrito por Lúcio Figueiredo
Um dos problemas mais clássicos da matemática computacional consiste em encontrar maneiras eficientes para descobrir se um número é primo ou não, ou seja, realizar um teste de primalidade. Nesta aula, abordaremos um algoritmo simples para realizar testes de primalidade e encontrar divisores e fatores primos de um inteiro qualquer.
Teste de Primalidade em 
Para checar se um certo número inteiro é primo ou não, podemos imaginar o seguinte simples algoritmo: Para cada número
tal que
, testamos se
é um divisor de
, ou seja, se
. Se sim,
é certamente um número composto. Senão, os únicos divisores de
são
e o próprio
, e logo,
é um número primo.
O problema do algoritmo acima é que a sua complexidade é , o que, dependendo da situação, pode ser muito ineficiente. Para uma otimização significativa, vamos utilizar o seguinte lema:
Lema 1: Um número inteiro é composto se, e somente se este possui um divisor próprio
(ou seja, um divisor diferente de
e de
) menor ou igual a
.
Prova: Se possui um divisor próprio menor ou igual a
,
certamente será composto. Vamos agora provar a outra parte, o "somente se": Seja
um divisor próprio qualquer de
. Perceba que
também é um divisor próprio de
. Vamos analisar dois casos:
: Este caso é trivial, pois
já é um divisor que satisfaz o lema.
: Neste caso, teremos que
. Logo, o divisor
já torna o lema verdadeiro.
Como em ambos os casos o lema é verdadeiro, terminamos a prova.
Utilizando o lema acima, sabemos que um número é primo se, e somente se não possui nenhum divisor entre e
. Logo, podemos otimizar nosso algoritmo inicial testando apenas se existe algum inteiro
tal que
e
divide
. Assim, a complexidade do algoritmo otimizado será
. Confira o código abaixo:
Divisores de um inteiro
Imagine que temos o seguinte problema: Dado um número inteiro , queremos encontrar todos os divisores positivos de
. Uma possível solução seria, novamente, iterar por todos os números de
a
e checar quais deles dividem
, salvando-os em um vetor de respostas. Dessa forma, obtemos uma complexidade de
.
Para otimizar este algoritmo, perceba que se é um divisor de
maior que
, então o número
também é um divisor de
e
. Isso sugere que é suficiente iterarmos apenas pelos números de
a
, e, assim que encontrarmos um divisor
tal que
, inserimos tanto
quanto
em nosso vetor de respostas. Dessa forma, encontraremos tanto os divisores "pequenos" (menores ou iguais a
) de
quanto os divisores "grandes" (maiores que
).
Confira o código para melhor entendimento:
Fatoração de um inteiro
Imagine que agora queremos encontrar todos os divisores primos de , ou seja, queremos encontrar a fatoração de
em números primos. Inicialmente, observe que o menor divisor próprio de um número composto é sempre um número primo. Além disso, pelo Lema 1, sabemos que este menor divisor é sempre menor ou igual a
.
Estas duas observações indicam que podemos realizar o seguinte algoritmo:
- Encontre o menor divisor
de
e adicione
à fatoração.
- Divida
por
até que o número resultante não seja mais um múltiplo de
.
- Repita os passos
e
até que o número resultante seja primo ou igual a
. Caso o número seja diferente de
, inclua-o na fatoração de
.
Essencialmente, iremos dividir o número sempre pelo seu menor fator, que é sempre um número primo, até que este fator não o divida mais. Desta maneira, o menor divisor do número resultante será o próximo divisor primo de
, e assim sucessivamente. Como o divisor
será sempre menor ou igual a
, a complexidade do algoritmo será (também!)
.
Confira o código abaixo para melhor entendimento: