結果
| 問題 |
No.8030 ミラー・ラビン素数判定法のテスト
|
| ユーザー |
かりあげクン
|
| 提出日時 | 2020-08-27 01:08:31 |
| 言語 | Haskell (9.10.1) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 3,251 bytes |
| コンパイル時間 | 4,734 ms |
| コンパイル使用メモリ | 201,088 KB |
| 実行使用メモリ | 8,320 KB |
| 最終ジャッジ日時 | 2024-11-18 18:17:27 |
| 合計ジャッジ時間 | 4,012 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 4 WA * 6 |
コンパイルメッセージ
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
ソースコード
{-# OPTIONS_GHC -O2 #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE MagicHash #-}
import qualified Control.Arrow as Arrow
import qualified Control.Monad as Monad
import qualified Data.Bool as Bool
import qualified Data.Bits as Bits
import qualified Data.ByteString.Char8 as BSC8
import qualified Data.Foldable as Foldable
import qualified Data.List as List
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import qualified Data.Word as Word
import Unsafe.Coerce
-----------
-- input --
-----------
type Parser a = BSC8.ByteString -> Maybe (a, BSC8.ByteString)
parseInt :: Parser Int
parseInt = fmap (Arrow.second BSC8.tail) . BSC8.readInt
parseChar :: [Char] -> VU.Vector Char
parseChar = VU.fromList
parse1 :: IO Int
parse1 = readLn
parse2 :: IO (Int, Int)
parse2 = (\vec -> (vec VU.! 0, vec VU.! 1)) . VU.unfoldrN 2 parseInt <$> BSC8.getLine
parse3 :: IO (Int, Int, Int)
parse3 = (\vec -> (vec VU.! 0, vec VU.! 1, vec VU.! 2)) . VU.unfoldrN 3 parseInt <$> BSC8.getLine
parseM :: Int -> IO (VU.Vector Int)
parseM m = VU.unfoldrN m parseInt <$> BSC8.getLine
parseN :: Int -> IO (VU.Vector Int)
parseN n = VU.replicateM n parse1
parseNM :: Int -> Int -> IO (V.Vector (VU.Vector Int))
parseNM n m = V.replicateM n $ VU.unfoldrN m parseInt <$> BSC8.getLine
main :: IO ()
main = do
n <- parse1
xs <- parseN n
Monad.forM_ [0..n-1] $ \i -> do
putStrLn $ show (xs VU.! i) ++ " " ++ Bool.bool "0" "1" (millerRabin $ xs VU.! i)
millerRabin :: Int -> Bool
millerRabin n
| n <= 1 = False
| n == 2
|| n == 3
|| n == 5
|| n == 7 = True
| even n = False
| otherwise = mrCheck n
powMod :: Int -> Int -> Int -> Int
powMod x n modulus
| x > modulus = powMod (x `mod` modulus) n modulus
| n == 0 = 1
| n == 1 = x `mod` modulus
| x == 0 = 0
| x == 1 = 1
| even n = z * z `mod` modulus
| otherwise = z * z * (x `mod` modulus) `mod` modulus
where z = powMod x (n `div` 2) modulus
factoringPowers :: Int -> (Int, Int)
factoringPowers n = loop n 0
where
loop d s
| even d = loop (d `div` 2) (s + 1)
| otherwise = (s, d)
mrCheck :: Int -> Bool
mrCheck p
| p < 2047 = loop [2]
| p < 1373653 = loop [2,3]
| p < 9080191 = loop [31,73]
| p < 25326001 = loop [2,3,5]
| p < 4759123141 = loop [2,7,61]
| p < 1122004669633 = loop [2,13,23,1662803]
| p < 2152302898747 = loop [2,3,5,7,11]
| p < 3474749660383 = loop [2,3,5,7,11,13]
| p < 341550071728321 = loop [2,3,5,7,11,13,17]
| p < 3825123056546413051 = loop [2,3,5,7,11,13,17,19,23]
| otherwise = loop [2,325,9375,28178,450775,9780504,1795265022]
where
m = p - 1
(s, d) = factoringPowers m
loop [] = True
loop (a:as)
| (powMod a d p) /= 1 && powLoop 0 = False
| otherwise = loop as
where
powLoop r
| r < s = (powMod a (2 ^ r * d) p) /= m && powLoop (r + 1)
| otherwise = True
かりあげクン