import Control.Monad
import Control.Monad.ST
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Unboxed.Mutable as VM

-- haskell can be this iterative!
sieve :: Int -> V.Vector Bool
sieve upto = runST $ do
    s <- VM.replicate (upto+1) True
    VM.write s 0 False
    VM.write s 1 False
    forM_ [2..(ceiling.sqrt.fromIntegral $ upto)] $ \i -> do
        isP <- VM.read s i
        when isP $ forM_ [i*i, i*i+i..upto] (\n -> VM.write s n False)
    V.unsafeFreeze s

numPrimes :: Int -> Int
numPrimes = V.length . V.filter id . sieve

main = getContents >>= mapM_ (print . numPrimes . read) . lines