Peneira de Eratóstenes além de O (n). Prova

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 algoritmo
Embora 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)<x
p in mathcalP=>lp(p)=p

Prova


Lema 1 : lp(x) lelp(rd(x)), forallx notin mathcalP,x>1
Prova : 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.
 quadrado

Vamos 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.
 quadrado

Agora 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) lei1, 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.

 quadrado

Pela 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+n1<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).

Source: https://habr.com/ru/post/pt452388/


All Articles