Problem:
素数 II

素数というのは、1 よりも大きくそれ自身か 1 でしか割りきれない整数をいいます。例えば、2 は、2 と 1 でしか割り切れないので素数ですが、12 は、12 と 1 のほかに、2, 3, 4, 6 で割りきれる数なので素数ではありません。

整数 n を入力したとき、n より小さい素数のうち最も大きいものと、n より大きい素数のうち最も小さいものを出力するプログラムを作成してください。

Input

複数のデータセットが与えられます。各データセットに n (3 ≤ n ≤ 50,000) が１行に与えられます。

データセットの数は 50 を超えません。

Output

各データセットに対して、n より小さい素数のうち最大のものと、n より大きい素数のうち最小のものを１つのスペースで区切って１行に出力して下さい。

Sample Input

19
3517

Output for the Sample Input

17 23
3511 3527

Solution in Haskell (judge verdict: Accepted)

import Control.Applicative
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

primes :: Int -> [Int]
primes = V.toList . V.map fst . V.filter snd . V.imap (,) . sieve

findRange :: Ord a => [a] -> a -> (a,a)
findRange (x:p@(y:_)) a = if x < a && not (y < a)
                              then (x, head . dropWhile (<= a) $ p)
                              else findRange p a

main = do
    let
        ps = primes 50100
        f = findRange ps
    getContents >>=
        mapM_ ((\(p0,p1) -> putStrLn . unwords . map show $ [p0,p1])
                . f . read) . lines