import Control.Applicative import Control.Exception.Base import Control.Monad import Data.Array.ST import Data.Array.Unboxed import Data.Int -- 素数の無限リスト -- 参考: http://qiita.com/little_Haskeller/items/614a3ae20a517c19bb1f primes :: Integral a => [a] primes = [2, 3, 5] ++ sieve 5 7 (drop 2 primes) where sieve m s (p : ps) = [n | n <- ns, gcd m n == 1] ++ sieve (m * p) (p * p) ps where ns = [x + y | x <- [s, s + 6 .. p * p - 2], y <- [0, 4]] sieve _ _ [] = error "Unexpected" -- 上記の素数リストをもとに、与えられた数の素数判定を行う -- 参考: https://wiki.haskell.org/Testing_primality isPrime :: Integral a => a -> Bool isPrime n = n > 1 && foldr (\p r -> p * p > n || (mod n p /= 0 && r)) True primes -- 素数計数関数の表をつくる -- 添え字と内容をInt64に決め打ちしている pcfTable :: Int64 -> UArray Int64 Int64 pcfTable n = runSTUArray $ do t <- newArray_ (0, n) writeArray t 0 0 forM_ [1 .. n] $ \i -> do pre <- readArray t $ i - 1 writeArray t i $ if isPrime i then pre + 1 else pre return t -- 鴨等素数間隔列の数を数える countSeqs :: Int64 -> Int64 -> Int64 countSeqs n l | x0Max < 0 = 0 | otherwise = sum [pcf ! dMax x0 | x0 <- [0 .. x0Max]] where -- x0がとれる最大値 x0Max = l - n + 1 -- 各x0に対して、dの最大値が決まる dMax x0 = (l - x0) `div` (n - 1) pcf = pcfTable $ dMax 0 -- ここからassert用の定数 minN :: Int64 minN = 3 maxN :: Int64 maxN = 1000000 minL :: Int64 minL = 1 maxL :: Int64 maxL = 5000000 -- ここまでassert用の定数 main :: IO () main = do [n, l] <- fmap read . words <$> getLine -- ここではテストケースが制約を満たしているかを確認するためassertを使用している -- 単に解くだけなら次のようにすればよい: print $ countSeqs n l let ans = assert (minN <= n && n <= maxN && minL <= n && n <= maxL) $ countSeqs n l print ans