結果
| 問題 |
No.407 鴨等素数間隔列の数え上げ
|
| コンテスト | |
| ユーザー |
はむ吉🐹
|
| 提出日時 | 2016-07-09 17:17:40 |
| 言語 | Haskell (9.10.1) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 2,072 bytes |
| コンパイル時間 | 11,311 ms |
| コンパイル使用メモリ | 193,920 KB |
| 実行使用メモリ | 48,256 KB |
| 最終ジャッジ日時 | 2024-10-13 10:20:27 |
| 合計ジャッジ時間 | 11,489 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 5 |
| other | AC * 28 TLE * 1 -- * 2 |
コンパイルメッセージ
Loaded package environment from /home/judge/.ghc/x86_64-linux-9.8.2/environments/default [1 of 2] Compiling Main ( Main.hs, Main.o ) [2 of 2] Linking a.out
ソースコード
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
はむ吉🐹