Cod sursa(job #2376941)

Utilizator alexghitaAlexandru Ghita alexghita Data 8 martie 2019 19:21:27
Problema Ciurul lui Eratosthenes Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.54 kb
/**
 * Folosim Ciurul lui Eratostene pentru a obține toate numerele prime până la N,
 * după care le numărăm și afișăm rezultatul.
 * 
 * O implementare eficientă a ciurului se poate găsi în acest articol:
 * https://infoarena.ro/ciurul-lui-eratostene
 */

#include <bits/stdc++.h>

using namespace std;

const int NMAX = 1000001;

bool sieved[NMAX];

// Marcheză numerele compuse până la n folosind Ciurul lui Eratostene, astfel
// încât doar numerele prime mai mici ca n vor fi nemarcate.
void compute_sieve(int n) {
  /**
   * Parcurgem numerele de la 1 la sqrt(n), ignorându-le pe cele pare, deoarece
   * știm că doar 2 este par și prim. În acest caz, sieved[i] = false înseamnă
   * că numărul 2*i + 1 nu a fost „cernut”, adică este prim.
   * 
   * Ne oprim când 2*i + 1 = sqrt(n). Acestui număr îi corespunde un indice x,
   * astfel încât:
   *     2x + 1 = (2*i + 1)^2 <=>
   *          x = 2*i^2 + 2*i,
   * de unde condiția for loop-ului exterior, cât și valoarea inițială a lui j
   * în for loop-ul interior.
   */
  for (int i = 1; ((i * i) << 1) + (i << 1) <= n; ++i) {
    if (!sieved[i]) {
      for (int j = ((i * i) << 1) + (i << 1); (j << 1) + 1 <= n; 
           j += (i << 1) + 1) {
        sieved[j] = true;
      }
    }
  }
}

int main() {
  stdin = freopen("ciur.in", "r", stdin);
  stdout = freopen("ciur.out", "w", stdout);

  int N;
  cin >> N;

  compute_sieve(N);

  int primes_found = 0;

  for (int i = 0; i < N / 2; ++i) {
    if (!sieved[i]) {
      primes_found++;
    }
  }
  cout << primes_found;
}