{-# OPTIONS_GHC -O2 #-} import Control.Monad import Control.Monad.ST import Data.Array.ST import Data.Array.Unboxed import Data.Char main = do s <- getContents forM_ (takeWhile (isDigit . head) $ words s) $ \w-> do -- let ps = primesTo (read w) -- print (length ps, last ps) -- leaks badly print (lastPrimes (read w)) -- no leak sieveUA :: Int -> UArray Int Bool sieveUA top = runSTUArray $ do let m = (top-1) `div` 2 r = floor . sqrt . fromIntegral $ top + 1 sieve <- newArray (1,m) True -- :: ST s (STUArray s Int Bool) forM_ [1..r `div` 2] $ \i -> do isPrime <- readArray sieve i when isPrime $ -- ((2*i+1)^2-1)`div`2 = 2*i*(i+1) forM_ [2*i*(i+1), 2*i*(i+2)+1..m] $ \j -> writeArray sieve j False return sieve primesTo :: Int -> [Int] primesTo top = 2 : [i*2+1 | (i,True) <- assocs $ sieveUA top] lastPrimes :: Int -> (Int,[Int]) -- (nth, vals) lastPrimes top = let arr = sieveUA top (b,t) = bounds arr in ( 1 + length [() | (i,True) <- assocs arr] , (if (top < 13) then (2:) else id) $ reverse $ take 5 [ 2*i+1 | i <- [t,t-1..b], arr ! i ] ) {- ST Array [Int] ON ODDS -= n =- -= top =- 30,000: 350,377: 0.01s 3.7MB 100,000: 1,299,709: 0.03s 3.7MB 300,000: 4,256,233: 0.10s 3.7MB 1 mln --> 15,485,863: 0.43s 4.8MB time space (s_0=3.7) 2 mln --> 32,452,843: 0.98s 5.8MB 4 mln --> 67,867,967: 2.31s 8.9MB 1m-> n^1.21 n^1.12 5 mln --> 86,028,121: 3.04s 9.9MB 6 mln --> 104,395,301: 3.77s 10.9MB (leak: was: ***6.7s-227MB***!!!) **** 6,500,000-> 113,648,393: 4.14s 10.9MB 7 mln --> 122,949,823: 4.52s 11.9MB 7,538,613-> 133,000,999: 4.95s 11.9MB 8 mln --> 141,650,939: 5.32s 13.0MB 4m-> n^1.20 n^0.84 9 mln --> 160,481,183: 6.12s 14.0MB 10 mln --> 179,424,673: 6.91s 15.0MB 15 mln --> 275,604,541: 11.01s 21.1MB 18 mln --> 334,214,459: 13.65s 24.2MB 8m-> n^1.16 n^0.97 (1m->n^1.01) 20 mln --> 373,587,883: TIMEOUT -}