Cod sursa(job #3362664)

Utilizator Sorin123-21Enachioiu Sorin-Catalin Sorin123-21 Data 11 august 2026 12:24:21
Problema Ciurul lui Eratosthenes Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.69 kb
#include <array>
#include <bit>
#include <cstdint>
#include <cstdio>
#include <iostream>

constexpr int MAX_N = 2'000'000;

constexpr std::size_t ODD_COUNT =
    (MAX_N + 1) / 2;

constexpr std::size_t WORD_COUNT =
    (ODD_COUNT + 63) / 64;

struct SieveData {
    std::array<std::uint64_t, WORD_COUNT> bits{};
    std::array<std::uint32_t, WORD_COUNT + 1> prefix{};
};


constexpr bool isPrimeOdd(const SieveData& sieve, int x)
{
    const std::size_t index =
        static_cast<std::size_t>(x >> 1);

    return (sieve.bits[index >> 6] >> (index & 63)) & 1ULL;
}


constexpr void clearOdd(SieveData& sieve, int x)
{
    const std::size_t index =
        static_cast<std::size_t>(x >> 1);

    sieve.bits[index >> 6] &=
        ~(1ULL << (index & 63));
}


consteval SieveData makeSieve()
{
    SieveData sieve{};

    for (auto& word : sieve.bits) {
        word = ~0ULL;
    }

    clearOdd(sieve, 1);

    constexpr int STEP = 6;
    constexpr int SPLIT =
        9 + 200'000 * STEP;  

    for (int multiple = 9;
         multiple < SPLIT;
         multiple += STEP) {

        clearOdd(sieve, multiple);
    }

    for (int multiple = SPLIT;
         multiple <= MAX_N;
         multiple += STEP) {

        clearOdd(sieve, multiple);
    }

    for (int p = 5; p * p <= MAX_N; p += 2) {

        if (!isPrimeOdd(sieve, p)) {
            continue;
        }

        for (int multiple = p * p;
             multiple <= MAX_N;
             multiple += 2 * p) {

            clearOdd(sieve, multiple);
        }
    }

    if constexpr (ODD_COUNT % 64 != 0) {
        sieve.bits.back() &=
            (1ULL << (ODD_COUNT % 64)) - 1;
    }

    for (std::size_t i = 0; i < WORD_COUNT; ++i) {
        sieve.prefix[i + 1] =
            sieve.prefix[i] +
            std::popcount(sieve.bits[i]);
    }

    return sieve;
}

inline constexpr SieveData SIEVE = makeSieve();


constexpr int countPrimesUpTo(int n)
{
    if (n < 2) {
        return 0;
    }

    std::uint32_t answer = 1;

    const std::size_t oddCount =
        static_cast<std::size_t>((n + 1) / 2);

    const std::size_t completeWords =
        oddCount >> 6;

    const unsigned remainingBits =
        static_cast<unsigned>(oddCount & 63);

    answer += SIEVE.prefix[completeWords];

    if (remainingBits != 0) {

        const std::uint64_t mask =
            (1ULL << remainingBits) - 1;

        answer += std::popcount(
            SIEVE.bits[completeWords] & mask
        );
    }

    return static_cast<int>(answer);
}


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

    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;

    std::cout << countPrimesUpTo(n) << '\n';

    return 0;
}