Nos comentários de um dos 
posts anteriores sobre a peneira de Eratóstenes, esse pequeno algoritmo da 
Wikipedia foi mencionado:
Algoritmo 1:1:  i := 2, 3, 4, ...,  n: 2:  lp[i] = 0: 3: lp[i] := i 4: pr[] += {i} 5:  p  pr  p ≤ lp[i]  p*i ≤ n: 6: lp[p*i] := p : lp -        n pr -     n. 
O algoritmo é simples, mas não para todos parecia óbvio. O principal problema é que não há evidências na Wikipedia, e o 
link para a fonte ( 
pdf ) contém um algoritmo bastante diferente do acima.
Neste post, tentarei, espero, ser possível provar que esse algoritmo não apenas funciona, mas também por complexidade linear.
Uma observação sobre a complexidade do algoritmoEmbora esse algoritmo seja assintoticamente mais rápido que o 
crivo padrão 
de Eratóstenes em O (n log log n), requer muito mais memória. Portanto, para n verdadeiramente grande, sempre que esse algoritmo brilha em toda a sua glória, ele não é aplicável. No entanto, é muito útil mesmo para n pequeno, se você precisar não apenas encontrar todos os números primos, mas também fatorar rapidamente todos os números até n.
 Definições
 m a t h c a l P - muitos números primos.
l p ( x ) - divisor principal mínimo de um número: 
lp (x) = min \ {p \ in \ mathcal {P} \ \ vert \ p \ vert x \}lp (x) = min \ {p \ in \ mathcal {P} \ \ vert \ p \ vert x \}rd(x) - outros fatores: 
rd(x)=x/lp(x)Observe que todas as definições acima são para 
x ge2 .
Algumas propriedades óbvias das funções apresentadas acima, que serão usadas posteriormente:
lp(a timesb)=min(lp(a),lp(b))rd(x)<xp in mathcalP=>lp(p)=pProva
Lema 1 : 
lp(x) lelp(rd(x)), forallx notin mathcalP,x>1Prova : Porque qualquer divisor 
rd(x) também um divisor 
x e 
lp(x) não é superior a qualquer divisor 
x então 
lp(x) não excede nenhum divisor 
rd(x) incluindo o menor deles. O único problema com esta afirmação é se 
rd(x) não possui divisores simples, mas isso só é possível se 
x in mathcalP , que é excluído na condição do lema.
 quadradoVamos 
E = \ {(lp (x), rd (x)) \ vert \ forall x \ notin \ mathcal {P}, 2 \ le x \ le n \}Porque 
lp(x) vezesrd(x)=x (por definição 
rd() ), se nos dessem muito 
E então poderíamos calcular 
lp() para todos os números compostos até n. Isso é feito, por exemplo, pelo seguinte algoritmo:
Algoritmo 2: 1:   (l,r)  E: 2: lp[l*r] := l; 
Note que 
 vertE vert len portanto, o algoritmo 2 acima funciona para complexidade linear.
Além disso, vou provar que o algoritmo 1 da Wikipedia na verdade apenas repete todos os elementos desse conjunto, porque pode ser parametrizado de uma maneira diferente.
Vamos 
E '= \ {(p, r) \ vert p \ in \ mathcal {P}, 2 \ le r <n, p \ le lp (r), p \ vezes r \ le n \}Lema 2 : 
E=E′Prova :
Vamos 
(a,b) emE => 
 existex nãoem mathcalP, 2 arquivox arquivon meioa=lp(x),b=rd(x) .
Por definição 
lp(),rd() : 
a in mathcalP , 
a vezesb=x . Pelo lema 1, 
a lelp(b) .
porque 
rd(x)<x então 
b<n .
Desde 
x notin mathcalP , 
b ge2 .
Além disso, por definição 
E , 
x len portanto 
a vezesb len .
Todas as 4 condições 
E′ meios cumpridos 
(a,b) emE′ => 
E subconjuntoE′ .
Vamos 
(a,b) emE′ . Vamos 
x=a vezesb .
Por definição 
E′ , 
a in mathcalP . Meios 
a - divisão simples 
x .
lp(x)=lp(a vezesb)=min(lp(a),lp(b))=min(a,lp(b))Porque 
a lelp(b) então 
lp(x)=a. Meios 
b=rd(x).Por definição, 
x=a timesb len. Obviamente também 
x=a timesb ge2.Todas as condições para 
E concluído => 
E′ subconjuntoE.Portanto, 
E=E′. quadradoAgora resta escolher os corretos 
r e 
p da definição do conjunto 
E′ e aplique o algoritmo 2. É exatamente isso que o algoritmo 1 faz (apenas a variável i é usada em vez de r). Mas há um problema! Para classificar todos os elementos de um conjunto 
E′ calcular 
lp, precisamos saber 
lp, porque existe uma condição na definição 
p lelp(r) .
Felizmente, esse problema contorna a ordem de classificação correta. É necessário resolver 
r no loop externo e 
p - por dentro. Então 
lp(r) já será calculado. Este fato é comprovado pelo seguinte teorema.
Teorema 1:O algoritmo 1 suporta a seguinte invariante: Após a iteração do loop externo para i = k, todas as primas até k inclusive serão destacadas em pr. Também será contado 
lp() para todos 
x notin mathcalP meiox len, rd(x) lek na matriz lp.
Prova :
Provamos por indução. Para k = 2, a invariante é verificada manualmente. O único primo 2 será adicionado à lista pr, porque a matriz lp [] é inicialmente preenchida com zeros. Além disso, o único número composto em que 
rd(x) le2 - este é 4. É fácil verificar se o loop interno será executado exatamente uma vez (para n> 3) e executará corretamente lp [4]: = 2.
Agora, suponha que o invariante seja válido para a iteração i = k-1. Vamos provar que também será válido para a iteração i = k.
Para fazer isso, basta verificar se o número i, se for primo, será adicionado à lista pr e se 
lp() será contado para todos os números compostos 
x n, incluindo 
rd(x)=i. São esses números da invariante para k que ainda não estão cobertos pela invariante para k-1.
Se i for simples, lp [i] será 0, porque a única operação de gravação no array lp, que teoricamente poderia calcular lp [i] (na linha 6), sempre grava em índices compostos, porque p * i (para i> 1) - sempre composto. Portanto, o número i será adicionado à lista de números primos. Além disso, na linha 3, lp [i] será contado.
Se i for composto, no início da iteração lp [i] já será calculado pela invariante para i = k-1, porque 
rd(i)<i ou 
rd(i) lei−1, portanto, eu cai sob a condição invariável na iteração anterior. Portanto, o número composto i não será adicionado à lista de números primos.
Além disso, tendo o lp [i] correto e todos os números primos até i inclusive, o loop nas linhas 5-6 iterará sobre todos os elementos 
(p,i) emE′ em que a segunda parte é i:
- p emP, porque é da lista pr
- p lelp(i), por condição para parar o ciclo
- p vezesi len, por condição para parar o ciclo
- i<n, segue de p vezesi len, p>1
Todos os primos necessários na lista pr são, porque apenas números até 
lp(i) lei . Portanto, os valores lp [] serão calculados para todos os números compostos 
x para qual 
rd(x)=i . Esses são exatamente todos os números que estavam faltando durante a transição da invariante para k-1 para a invariante para k.
Portanto, o invariante vale para qualquer i = 2..n.
 quadradoPela invariante do Teorema 1 para i = n, todos os números primos até n e todos os lp [] serão calculados pelo algoritmo 1.
Além disso, como nas linhas 5-6, vários elementos do conjunto são classificados 
E , o loop interno total não executará mais 
 vertE vert<n operações. A operação de verificação no loop será executada sem problemas 
 vertE vert+n−1<2n vezes ( 
 vertE vert vezes retornará verdadeiro e n-1 vezes, para cada i retornará falso). Todas as operações restantes são aninhadas em um ciclo em i de 2 para n.
Daqui resulta que a complexidade do algoritmo 1 é O (n).