import Control.Applicative

main :: IO ()
main = do
  n <- readLn
  loop n []

loop 0 _ = return ()
loop n dic = do
  [c, s] <- words <$> getLine
  if c == "insert"
    then loop (n - 1) (s : dic)
    else do
    putStrLn (if elem s dic then "yes" else "no")
    loop (n - 1) dic

Global OOD problem IDs are disjoint from train, validation, and in-distribution test problem IDs.

Search III

Your task is to write a program of a simple dictionary which implements the following instructions:

insert str: insert a string str in to the dictionary

find str: if the distionary contains str, then print 'yes', otherwise print 'no'

Input

In the first line n, the number of instructions is given. In the following n lines, n instructions are given in the above mentioned format.

Output

Print yes or no for each find instruction in a line.

Constraints

A string consists of 'A', 'C', 'G', or 'T'

1 ≤ length of a string ≤ 12

n ≤ 1000000

Sample Input 1

5
insert A
insert T
insert C
find G
find A

Sample Output 1

no
yes

Sample Input 2

13
insert AAA
insert AAC
insert AGA
insert AGG
insert TTT
find AAA
find CCC
find CCC
insert CCC
find CCC
insert T
find TTT
find T

Sample Output 2

yes
no
no
yes
yes
yes

Notes

Template in C

Submitted source-code file size, in bytes.

Execution CPU time reported by official Project CodeNet metadata, in milliseconds.

Peak memory usage reported by official Project CodeNet metadata, in kilobytes.


{-# LANGUAGE OverloadedStrings #-}

import qualified Data.ByteString as BS
import qualified Data.Map.Strict as Map
import Control.Applicative

main :: IO ()
main = do
  n <- readLn
  loop n Map.empty

splitSpace :: BS.ByteString -> [BS.ByteString]
splitSpace = BS.split 32

loop 0 _   = return ()
loop n dic = do
  [c, s] <- splitSpace <$> BS.getLine
  case c of
    "insert" -> loop (n - 1) (Map.insert s n dic)
    "find" -> do
      putStrLn (if Map.member s dic then "yes" else "no")
      loop (n - 1) dic


{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString.Char8 as BC
import Data.ByteString (ByteString)
import qualified Data.Set as S
-- Should I implement this myself?
import Control.Monad

data Command = Insert ByteString
             | Find ByteString

fromString :: ByteString -> Command
fromString s = let (cmd:str:_) = BC.words s
                   in
                   case cmd of
                        "insert" -> Insert str
                        "find" -> Find str

follow :: S.Set ByteString -> [Command] -> IO ()
follow s [] = return ()
follow !s (c:cs) = case c of
                       Insert str -> follow (S.insert str s) cs
                       Find str -> do
                           putStrLn $ if str `S.member` s
                                         then "yes"
                                         else "no"
                           follow s cs

main = do
    n <- readLn
    replicateM n BC.getLine >>= follow (S.empty) . map fromString


{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString.Char8 as BC
import Data.ByteString (ByteString)
import qualified Data.Set as S
-- Should I implement this myself?
import Control.Monad

data Command = Insert Int
             | Find Int

fromString :: ByteString -> Command
fromString s = let (cmd:str:_) = BC.words s
                   n = fromStr str
                   in
                   case cmd of
                        "insert" -> Insert n
                        "find" -> Find n

fromStr :: ByteString -> Int
fromStr = BC.foldl' (\acc c -> 5*acc + case c of
                                        'A' -> 1
                                        'T' -> 2
                                        'G' -> 3
                                        'C' -> 4) 0

follow :: S.Set Int -> [Command] -> IO ()
follow s [] = return ()
follow s (c:cs) = case c of
                       Insert str -> follow (S.insert str s) cs
                       Find str -> do
                           putStrLn $ if str `S.member` s
                                         then "yes"
                                         else "no"
                           follow s cs

main = do
    n <- readLn
    replicateM n BC.getLine >>= follow S.empty . map fromString


import qualified Data.Map.Strict as Map

--only key map as dictionary
type Dictionary = Map.Map String ()

insert::Dictionary -> String -> Dictionary
insert dic x = Map.insert x () dic

find::Dictionary -> String -> Bool
find dic x = Map.member x dic

do_n::Dictionary -> Int -> IO()
do_n d 0 = return()
do_n d n = do
  order<-getLine
  let ord:v:[] = words order
  if ord == "insert" then do
    seq (insert d v) (do_n (insert d v) (n-1))
                     else do
    putStr (if (find d v) then "yes" else "no")
    putStr "\n"
    do_n d (n-1)

main::IO()
main = do
  nc<-getLine
  let n = read nc::Int
  do_n Map.empty n


{-# OPTIONS_GHC -O2 #-}

import qualified  Data.Map.Strict as Map

main = do
  n   <- readLn
  dictionary n Map.empty

dictionary n maps = do

-- Stop condition
  if n == 0 then return ()
  else do
    s' <- getLine
    let [fOI,str] = words s'

--Separate cases with find and insert
    if fOI == "find"
       then do
         putStrLn (findDic str maps)
         dictionary (n-1) maps
       else
         dictionary (n-1) (insertDic str maps)

--Because list is slow, use Data.Map
insertDic str maps = Map.insert str "yes" maps

--Corresponds when reference is not possible by using the lookup function
findDic   str maps
  | Map.lookup str maps == Nothing = "no"
  | otherwise                      = "yes"


{-# OPTIONS_GHC -O2 #-}

import qualified  Data.HashMap.Strict as Map

main = do
  n   <- readLn
  dictionary n Map.empty

dictionary n maps = do

-- Stop condition
  if n == 0 then return ()
  else do
    s' <- getLine
    let [fOI,str] = words s'

--Separate cases with find and insert
    if fOI == "find"
       then do
         putStrLn (findDic str maps)
         dictionary (n-1) maps
       else
         dictionary (n-1) (insertDic str maps)

--Because list is slow, use Data.Map
insertDic str maps = Map.insert str "yes" maps

--Corresponds when reference is not possible by using the lookup function
findDic   str maps
  | Map.lookup str maps == Nothing = "no"
  | otherwise                      = "yes"


{-# OPTIONS_GHC -O2 -funbox-strict-fields #-}
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
{-# OPTIONS_GHC -fno-warn-unused-binds #-}
{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
{-# LANGUAGE OverloadedStrings #-}
-- {-# LANGUAGE FlexibleContexts #-}
-- {-# LANGUAGE MultiWayIf #-}
-- {-# LANGUAGE BangPatterns #-}
-- {-# LANGUAGE ViewPatterns #-}
-- {-# LANGUAGE TupleSections #-}

import           System.IO hiding (char8)
import           Control.Applicative
import           Control.Monad
import           Data.List
import           Data.Tuple
import           Data.Int
import           Data.Char
import           Data.Function (on)
import           Data.Ord (comparing)
import           Data.Monoid (mappend)
import           Data.Array
-- import           Data.Array.Unboxed
-- import           Data.Array.IArray
-- import           Data.Array.ST
-- import           Data.Array.MArray
-- import           Data.Array.Unsafe
-- import           Data.Array.Base(unsafeRead, unsafeWrite)
-- import           Data.Array.IO
import           Data.Ix
import           Data.Maybe
-- import           Data.Monoid hiding ((<>))
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BL
import           Data.ByteString.Builder
-- import           Data.Graph
-- import           Data.Vector.Unboxed ((//), (++), (!), (!?))
-- import qualified Data.Vector.Unboxed as U
import           Data.IntSet (IntSet)
import qualified Data.IntSet as IntSet
-- import           Data.IntMap.Strict (IntMap)
-- import qualified Data.IntMap.Strict as IntMap
-- import           Data.Sequence ((|>), (<|), (><),ViewR(..), ViewL(..), Seq)
-- import qualified Data.Sequence              as Seq
-- import           Data.Foldable (toList, minimumBy)
-- import           Debug.Trace

main = do
  n <- readInt1 <$> BS.getLine
  qs <- map ((\[a,b] -> (BS.head a, encode b)) . BS.words) <$> replicateM n BS.getLine
  foldM solve IntSet.empty qs

encode = BS.foldr f 0 where
  f 'A' x = x * 5 + 1
  f 'C' x = x * 5 + 2
  f 'G' x = x * 5 + 3
  f 'T' x = x * 5 + 4

solve :: IntSet -> (Char, Int) -> IO IntSet
solve s ('i', k) = return $ IntSet.insert k s
solve s ('f', k) = putStrLn (if IntSet.member k s then "yes" else "no") >> return s

--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --

format :: Show a => Maybe a -> IO ()
format Nothing = putStrLn "NO"
format (Just a) = putStrLn "YES" >> print a

-- [1,2,3] -> 1 2 3
putIntN :: [Int] -> IO ()
putIntN [] = return ()
putIntN xs = BL.putStrLn . toLazyByteString . foldl1 mappend . intersperse (char8 ' ') $ map intDec xs

readInt1 :: BS.ByteString -> Int
readInt1 = fst . fromJust . BS.readInt

readInt2 :: BS.ByteString -> (Int,Int)
readInt2 = toTuple . readIntN

readInt3 :: BS.ByteString -> (Int,Int,Int)
readInt3 = toTriple . readIntN

readIntN :: BS.ByteString -> [Int]
readIntN =  map readInt1 . BS.words

readInt641 :: BS.ByteString -> Int64
readInt641 = fromIntegral . fst . fromJust . BS.readInteger

readInt642 :: BS.ByteString -> (Int64,Int64)
readInt642 = toTuple . readInt64N

readInt643 :: BS.ByteString -> (Int64,Int64,Int64)
readInt643 = toTriple . readInt64N

readInt64N :: BS.ByteString -> [Int64]
readInt64N =  map readInt641 . BS.words

readInteger1 :: BS.ByteString -> Integer
readInteger1 = fst . fromJust . BS.readInteger

readInteger2 :: BS.ByteString -> (Integer,Integer)
readInteger2 = toTuple . readIntegerN

readInteger3 :: BS.ByteString -> (Integer,Integer,Integer)
readInteger3 = toTriple . readIntegerN

readIntegerN :: BS.ByteString -> [Integer]
readIntegerN =  map readInteger1 . BS.words

toTuple :: [a] -> (a, a)
toTuple [x, y] = (x, y)

toTriple :: [a] -> (a, a, a)
toTriple [x, y, z] =(x, y, z)

fromTuple :: (a, a) -> [a]
fromTuple (x, y) = [x, y]

fromTriple :: (a, a, a) -> [a]
fromTriple (x, y, z) = [x, y, z]

-- if not applying, use "const"

applyTuple :: (a -> a') -> (b -> b') -> (a, b) -> (a', b')
applyTuple f g (x, y) = (f x, g y)

applyTriple :: (a -> a') -> (b -> b') -> (c -> c') -> (a, b, c) -> (a', b', c')
applyTriple f g h (x, y, z) = (f x, g y, h z)

-- @since 4.8.0.0
sortOn' :: Ord b => (a -> b) -> [a] -> [a]
sortOn' f =
  map snd . sortBy (comparing fst) . map (\x -> let y = f x in y `seq` (y, x))


import Control.Applicative
import Control.Monad
import Control.Monad.State
import Data.Map as M
type Dict a = M.Map a ()

main = do
  n <- readLn
  let dict = M.empty
  exec n dict

exec n d = evalStateT ( replicateM_ n $ do
                      [a,b] <- liftIO $ words<$>getLine
                      let command = toComm a b
                      command) d
toComm :: Ord a => String -> a -> StateT (Dict a) IO ()
toComm "insert" x = Main.insert x
toComm "find" x   = find x

insert :: Ord a => a -> StateT (Dict a) IO ()
insert x = modify (M.insert x ())

find :: Ord a => a -> StateT (Dict a) IO ()
find x = do
  ds <- get
  let res = M.lookup x ds
  if res == Nothing then liftIO $ putStrLn "no"
                    else liftIO $ putStrLn "yes"


type Result = ([String], [Bool])

dictionary :: Result -> String -> Result
dictionary (items, found) input
  | cmd == "insert" = (insert target items, found)
  | cmd == "find"   = (items, (find target items) : found)
  where inputs = words input
        cmd    = inputs !! 0
        target = inputs !! 1

insert :: String -> [String] -> [String]
insert x [] = [x]
insert x (y:ys)
  | x `compare` y == GT = y : (insert x ys)
  | otherwise           = x:y:ys

find :: String -> [String] -> Bool
find x [] = False
find x (y:ys)
  | x == y    = True
  | otherwise = find x ys

main = do
  _ <- getLine
  inputs <- fmap lines getContents
  let result = foldl dictionary ([], []) inputs
  mapM_ putStrLn (map yesno $ reverse $ snd result)

yesno :: Bool -> String
yesno True = "yes"
yesno False = "no"


import           Control.Applicative
import           Control.Monad

data Dict
    = Empty
    | Node Bool Dict Dict Dict Dict -- End, A, C, G, T
    deriving (Eq, Show)

node :: Dict
node = Node False Empty Empty Empty Empty

dinsert :: String -> Dict -> Dict
dinsert [] (Node _ a c g t) = Node True a c g t
dinsert ('A':xs) (Node e a c g t)
    | a == Empty = Node e (dinsert xs node) c g t
    | otherwise  = Node e (dinsert xs a) c g t
dinsert ('C':xs) (Node e a c g t)
    | c == Empty = Node e a (dinsert xs node) g t
    | otherwise  = Node e a (dinsert xs c) g t
dinsert ('G':xs) (Node e a c g t)
    | g == Empty = Node e a c (dinsert xs node) t
    | otherwise  = Node e a c (dinsert xs g) t
dinsert ('T':xs) (Node e a c g t)
    | t == Empty = Node e a c g (dinsert xs node)
    | otherwise  = Node e a c g (dinsert xs t)

dfind :: String -> Dict -> Bool
dfind [] (Node e _ _ _ _) = e
dfind ('A':xs) (Node _ a _ _ _)
    | a == Empty = False
    | otherwise  = dfind xs a
dfind ('C':xs) (Node _ _ c _ _)
    | c == Empty = False
    | otherwise  = dfind xs c
dfind ('G':xs) (Node _ _ _ g _)
    | g == Empty = False
    | otherwise  = dfind xs g
dfind ('T':xs) (Node _ _ _ _ t)
    | t == Empty = False
    | otherwise  = dfind xs t

solve :: [(Char, String)] -> IO ()
solve xs = go node xs
  where
    go _ [] = return ()
    go d ((a, b):ys)
        | a == 'i' = go (dinsert b d) ys
        | a == 'f' = do
            if dfind b d
                then putStrLn "yes"
                else putStrLn "no"
            go d ys

main :: IO ()
main = do
    n <- readLn :: IO Int
    xs <- fmap ((\[a, b] -> (head a, b)) . words) <$> replicateM n getLine
    solve xs


import Data.Hashable (hash)
import Data.Map (Map, empty, member, insert)
import Data.List (partition)
import Control.Monad (foldM_)

main :: IO ()
main = do
    getLine
    inputs <- fmap lines getContents :: IO [String]
    foldM_ solve empty inputs

solve :: Map Int String -> String -> IO (Map Int String)
solve dictionary input =
    if ope == 'i' then
        return $ insert key val dictionary
    else do
        if member key dictionary then
            putStrLn "yes"
        else
            putStrLn "no"
        return dictionary
  where
    val = last . words $ input
    key = hash val
    ope = head input


import qualified Data.Vector.Unboxed as VU
import qualified Data.ByteString.Char8 as B
import Data.Tuple.Extra

main = do
  let readInt = fmap (second B.tail) . B.readInt
  n <- readLn
  xs <- VU.unfoldrN n readInt <$> B.getLine
  print $ solve n xs

solve :: Int -> VU.Vector Int -> Int
solve n xs = VU.foldl (\x y -> (x + y) `mod` (1000000000 + 7)) 0 ys
  where
    ss = VU.scanl (+) 0 xs

    ys = VU.generate n $ \i -> (xs VU.! i) * ((ss VU.! n) - (ss VU.! (i+1)))

Score : 300 points

Problem Statement

Given are N integers A_1,\ldots,A_N.

Find the sum of A_i \times A_j over all pairs (i,j) such that 1\leq i < j \leq N, modulo (10^9+7).

Constraints

2 \leq N \leq 2\times 10^5

0 \leq A_i \leq 10^9

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
A_1 \ldots A_N

Output

Print \sum_{i=1}^{N-1}\sum_{j=i+1}^{N} A_i A_j, modulo (10^9+7).

Sample Input 1

3
1 2 3

Sample Output 1

11

We have 1 \times 2 + 1 \times 3 + 2 \times 3 = 11.

Sample Input 2

4
141421356 17320508 22360679 244949

Sample Output 2

437235829


main = do
  n <- readLn
  xs <- map read . words <$> getLine :: IO [Integer]
  print $ solve n xs

solve n xs = foldl (\x y -> (x + y) `mod` (1000000000 + 7)) 0 $ do
  i <- [1..n-1]
  return $ xs !! (i-1) * ((ss !! n) - (ss !! i))
  where
    ss = scanl (+) 0 xs


main = do
  n <- readLn
  xs <- map read . words <$> getLine :: IO [Integer]
  print $ solve n xs

solve n xs = foldl (\x y -> (x + y) `mod` (1000000000 + 7)) 0 $ do
  i <- [1..n-1]
  j <- [i+1..n]
  return $ xs !! (i-1) * xs !! (j-1)


import qualified Data.ByteString.Char8 as B
import Data.Maybe

value = 10^9+7

main = do
    n <- fst . fromJust . B.readInt <$> B.getLine
    aa <- map (fst . fromJust . B.readInt) . B.words <$> B.getLine
    print $ flip mod value . sum $ map (answer aa) [(i,j) | i <- [0..n-1], j <- [0..n-1],  i < j]

answer aa (i,j) = (aa!!i * aa!!j) `mod` value


main :: IO ()
main = do
    n <- readLn
    a <- getLine >>= return . words >>=  return . map read :: IO [Int]
    print $ solve 1000000007 n a

solve :: Int -> Int -> [Int] -> Int
solve m n xs = (`mod` m) . sum $ zipWith (\x y -> x * y `mod` m) xs . scanr (+) 0 $ tail xs


import qualified Data.Text.Lazy as T
import qualified Data.Text.Lazy.IO as T
import qualified Data.Text.Lazy.Read as T

main :: IO ()
main = do
  let
    modulus = 1000000007 :: Int
    modAdd :: Int -> Int -> Int
    modAdd x y = (x + y) `mod` modulus
    modMul :: Int -> Int -> Int
    modMul x y = (x * y) `mod` modulus
    go :: Int -> Int -> [Int] -> Int
    go s c (x : xs) = go (s `modAdd` (c `modMul` x)) (c `modAdd` x) xs
    go s c _        = s
  n <- unsafeTextToInt <$> T.getLine :: IO Int
  as <- map unsafeTextToInt . T.words <$> T.getContents :: IO [Int]
  print . go 0 0 $ as

unsafeTextToInt :: T.Text -> Int
unsafeTextToInt s = case T.signed T.decimal s of
  Right (n, _) -> n
{-# INLINE unsafeTextToInt #-}


import qualified Data.Text.Lazy as T
import qualified Data.Text.Lazy.IO as T
import qualified Data.Text.Lazy.Read as T

main :: IO ()
main = do
  let
    modulus = 1000000007 :: Int
    modAdd :: Int -> Int -> Int
    modAdd x y = (x + y) `mod` modulus
    modMul :: Int -> Int -> Int
    modMul x y = (x * y) `mod` modulus
  n <- unsafeTextToInt <$> T.getLine :: IO Int
  as <- map unsafeTextToInt . T.words <$> T.getLine :: IO [Int]
  let
    bs = scanl modAdd 0 as :: [Int]
  print . foldl modAdd 0 $ zipWith modMul bs as

unsafeTextToInt :: T.Text -> Int
unsafeTextToInt s = case T.signed T.decimal s of
  Right (n, _) -> n
{-# INLINE unsafeTextToInt #-}


import Data.List
import Data.Ord
import Data.Char
import Data.Ratio
import Data.Maybe

main = do
  n <- readLn :: IO Integer
  as <- map read . words <$> getLine :: IO [Integer]
  print $ mod (sum [x*y|(i,x)<-zip [1..] as, (j,y)<-zip [1..] as, i<j]) (10^9+7)


import Control.Monad
import Data.Maybe
import qualified Data.ByteString.Char8 as BS
import Data.List

readInt = fst . fromJust . BS.readInt
readIntList = map readInt . BS.words
getInt = readInt <$> BS.getLine
getIntList = readIntList <$> BS.getLine

main = do
    n <- getInt
    as <- getIntList
    let rs = scanr g 0 as
    let zs = zipWith f as (tail rs)
    let ans = foldl' g 0 zs
    print ans

f a b = (a * b) `mod` 1000000007
g a b = (a + b) `mod` 1000000007


{-# LANGUAGE BangPatterns        #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE MultiWayIf          #-}
{-# LANGUAGE RankNTypes          #-}
{-# LANGUAGE ScopedTypeVariables #-}
import           Control.Monad
import           Control.Monad.ST
import           Control.Monad.State
import           Control.Monad.Trans.State
import           Data.Array.IArray
import           Data.Array.ST
import           Data.Array.Unboxed
import           Data.Bits
import qualified Data.ByteString.Char8       as BS
import           Data.Char
import           Data.Int                    (Int64)
import           Data.List
import           Data.Maybe
import           Data.Proxy
import           Data.Sequence               (Seq ((:<|), (:|>)), ViewL ((:<)),
                                              ViewR ((:>)), viewl, viewr, (<|),
                                              (><), (|>))
import qualified Data.Sequence               as Seq
import qualified Data.Set                    as S
import           Data.STRef
import qualified Data.Vector                 as V
import qualified Data.Vector.Mutable         as VM
import qualified Data.Vector.Unboxed         as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import           Numeric

main :: IO ()
main = do
  n <- readLn :: IO Int
  as <- readLnAsUVecWith unconsInt n

  let partsum = VU.tail $ VU.postscanr' (\x y -> (x+y)`mod`modulus) 0 as
      partprod = VU.foldl1' (\x y -> (x+y)`mod`modulus) $ VU.zipWith (\x y -> (x*y)`mod`modulus) as partsum

  print partprod

modulus :: Int
-- modulus = 10^9 + 7
modulus = 1000000007

newtype IntMod = IntMod Int deriving Eq

-- fromIntegral_Int64_IntMod :: Int64 -> IntMod
-- fromIntegral_Int64_IntMod n = IntMod (n `mod` modulus)
-- {-# RULES
-- "fromIntegral/Int->IntMod"
--     fromIntegral = fromIntegral_Int64_IntMod . (fromIntegral :: Int -> Int64)
-- "fromIntegral/Int64->IntMod"
--     fromIntegral = fromIntegral_Int64_IntMod
-- #-}

instance Show IntMod where
  show (IntMod x) = show x

instance Num IntMod where
  IntMod x + IntMod y = IntMod ((x + y) `mod` modulus)
  IntMod x - IntMod y = IntMod ((x - y) `mod` modulus)
  IntMod x * IntMod y = IntMod ((x * y) `mod` modulus)
  fromInteger n = IntMod (fromInteger (n `mod` fromIntegral modulus))
  abs = undefined
  signum = undefined

im0 :: IntMod
im0 = 0

powMod :: IntMod -> Int64 -> IntMod
powMod !x 1 = x
powMod !x !k
  | even k = powMod (x * x) (k `div` 2)
  | otherwise = x * powMod (x * x) (k `div` 2)

-- converter
unconsChar :: StateT BS.ByteString Maybe Char
unconsChar = StateT BS.uncons

unconsInt :: StateT BS.ByteString Maybe Int
unconsInt = StateT $ BS.readInt . BS.dropWhile isSpace

unconsInteger :: StateT BS.ByteString Maybe Integer
unconsInteger = StateT $ BS.readInteger . BS.dropWhile isSpace

-- 1D Data
-- for list
readLnAsListWith :: StateT BS.ByteString Maybe a -> IO [a]
readLnAsListWith !st = unfoldr (runStateT st) <$> BS.getLine

-- for array (boxed or unboxed)
readLnAsArrayWith :: IArray a e => StateT BS.ByteString Maybe e -> Int -> IO (a Int e)
readLnAsArrayWith !st !n = listArray (1,n) <$> readLnAsListWith st

-- for boxed vector
readLnAsVecWith :: StateT BS.ByteString Maybe a -> Int -> IO (V.Vector a)
readLnAsVecWith !st !n = V.unfoldrN n (runStateT st) <$> BS.getLine

-- for unboxed vector
readLnAsUVecWith :: VU.Unbox a => StateT BS.ByteString Maybe a -> Int -> IO (VU.Vector a)
readLnAsUVecWith !st !n = VU.unfoldrN n (runStateT st) <$> BS.getLine

-- example: 1D tuple vector
readLnAsUVecWith2Tuple :: VU.Unbox a => StateT BS.ByteString Maybe a -> Int -> IO (VU.Vector (a,a))
readLnAsUVecWith2Tuple !st !n = VU.replicateM n $ (\vec -> (vec VU.! 0, vec VU.! 1)) <$> readLnAsUVecWith st 2

-- 2D Data
-- n: number of lines
-- m: number of values per a line

-- for boxed vector
readLnAs2DVecWith :: StateT BS.ByteString Maybe a -> Int -> Int -> IO (V.Vector a)
readLnAs2DVecWith !st !n !m = V.unfoldrN (n * m) (runStateT st) . BS.concat <$> replicateM n BS.getLine

readLnAs2DUVecWith :: VU.Unbox a => StateT BS.ByteString Maybe a -> Int -> Int -> IO (VU.Vector a)
readLnAs2DUVecWith !st !n !m = VU.unfoldrN (n * m) (runStateT st) . BS.concat <$> replicateM n BS.getLine


combinations :: Int -> [a] -> [[a]]
combinations n xs = comb n (length xs) xs where
  comb 0 _ _ = [[]]
  comb r n a@(x:xs)
    | n == r    = [a]
    | otherwise = map (x:) (comb (r - 1) (n - 1) xs) ++ comb r (n - 1) xs

main = do
 getLine
 aList <- map read . words <$> getLine :: IO [Integer]
 let a = combinations 2 aList
 let c = map (flip mod 1000000007) $ map product a
 let b = (foldl (+) 0 c) `mod` 1000000007
 print b


{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE BinaryLiterals #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE NumDecimals #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}

import Control.Applicative
import Control.Arrow
import Control.Monad
import Control.Monad.ST

import Data.Char
import Data.List
import Data.Maybe

import qualified Data.ByteString.Char8 as B

import Data.Array.ST.Safe
import Data.STRef

import Debug.Trace
import Text.Printf

readInt = readLn :: IO Int
readInteger = readLn :: IO Integer
readInts = map ( fst . fromJust . B.readInt ) . B.words <$> B.getLine
readIntegers = map ( fst . fromJust . B.readInteger ) . B.words <$> B.getLine

which a b f = if f then a else b
mp [ a, b ] = ( a, b )

modifyArray a i f = writeArray a i =<< f <$> readArray a i

printList [a] = print a
printList (a:as) = putStr ( show a ) >> putChar ' ' >> printList as

main = getLine >> readIntegers >>= print . solve

solve (a:as) = solve' a as

solve' _ [] = 0
solve' s (a:as) = ( s *% a ) +% solve' ( s +% a ) as

a +% b = ( a + b ) `mod` 1000000007
a *% b = a * b `mod` 1000000007


{-# LANGUAGE BangPatterns               #-}
{-# LANGUAGE BinaryLiterals             #-}
{-# LANGUAGE CPP                        #-}
{-# LANGUAGE DeriveFunctor              #-}
{-# LANGUAGE DerivingStrategies         #-}
{-# LANGUAGE DerivingVia                #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE KindSignatures             #-}
{-# LANGUAGE LambdaCase                 #-}
{-# LANGUAGE MagicHash                  #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE MultiWayIf                 #-}
{-# LANGUAGE NumericUnderscores         #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE PatternSynonyms            #-}
{-# LANGUAGE RankNTypes                 #-}
{-# LANGUAGE RecordWildCards            #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE StandaloneDeriving         #-}
{-# LANGUAGE TupleSections              #-}
{-# LANGUAGE TypeApplications           #-}
{-# LANGUAGE TypeFamilies               #-}
{-# LANGUAGE TypeInType                 #-}
{-# LANGUAGE UnboxedTuples              #-}
{- base -}
import           Control.Applicative
import qualified Control.Arrow                     as Arrow
import           Control.Monad
import           Control.Monad.ST
import           Data.Bits
import           Data.Bool
import qualified Data.Char                         as Char
import           Data.Complex
import qualified Data.Foldable                     as Foldable
import           Data.Function
import qualified Data.List                         as List
import           Data.Maybe
import           Data.Monoid
import           Data.Ord
import           Data.Ratio
import           Data.Semigroup
import qualified Data.Word                         as Word
import           Foreign                           hiding (void)
import           GHC.Exts
import           Unsafe.Coerce
{- array -}
import qualified Data.Array.IO                     as ArrIO
import qualified Data.Array.MArray                 as ArrMA
import qualified Data.Array.ST                     as ArrST
import qualified Data.Array.Storable               as ArrStore
import qualified Data.Array.Unboxed                as ArrU
{- bytestring -}
import qualified Data.ByteString                   as BS
import qualified Data.ByteString.Builder           as BSB
import qualified Data.ByteString.Builder.Extra     as BSBE
import qualified Data.ByteString.Char8             as BSC8
import qualified Data.ByteString.Lazy              as BSL
import qualified Data.ByteString.Lazy.Builder      as BSLB
import qualified Data.ByteString.Lazy.Char8        as BSLC8
import qualified Data.ByteString.Unsafe            as BSU
{- containers -}
import qualified Data.Graph                        as Graph
import           Data.IntMap                       (IntMap)
import qualified Data.IntMap                       as IntMap
import           Data.IntSet                       (IntSet)
import qualified Data.IntSet                       as IntSet
import qualified Data.Sequence                     as Seq
import qualified Data.Tree                         as Tree
{- integer-gmp -}
import           GHC.Integer.GMP.Internals
{- time -}
import qualified Data.Time.Calendar                as Calender
import qualified Data.Time.Calendar.Easter         as CalenderE
import qualified Data.Time.Calendar.Julian         as CalenderJ
import qualified Data.Time.Calendar.MonthDay       as CalenderM
import qualified Data.Time.Calendar.OrdinalDate    as CalenderD
import qualified Data.Time.Calendar.WeekDate       as CalenderW
import qualified Data.Time.LocalTime               as LocalTime
{- transformers -}
import qualified Control.Monad.Trans.Accum         as TAccum
import qualified Control.Monad.Trans.Cont          as TCont
import qualified Control.Monad.Trans.Identity      as TId
import qualified Control.Monad.Trans.Reader        as TReader
import qualified Control.Monad.Trans.State.Lazy    as TStateL
import qualified Control.Monad.Trans.State.Strict  as TStateS
import qualified Control.Monad.Trans.Writer.CPS    as TWriteC
import qualified Control.Monad.Trans.Writer.Lazy   as TWriteL
import qualified Control.Monad.Trans.Writer.Strict as TWriteS
{- vector -}
import qualified Data.Vector                       as V
import qualified Data.Vector.Generic               as VG
import qualified Data.Vector.Generic.Mutable       as VGM
import qualified Data.Vector.Mutable               as VM
import qualified Data.Vector.Primitive             as VP
import qualified Data.Vector.Primitive.Mutable     as VPM
import qualified Data.Vector.Unboxed               as VU
import qualified Data.Vector.Unboxed.Mutable       as VUM
-------------------------------------------------------------------------------
main :: IO ()
main = do
  n <- parse1
  a <- parseM n
  let p1 = snd $ VU.foldr func1 (IntSet.empty, True) a
  let p2 = (1 == VU.foldr1 gcd a)
  putStrLn $ if p1
              then "pairwise coprime"
              else if p2
                then "setwise coprime"
                else "not coprime"

func1 :: Int -> (IntSet, Bool) -> (IntSet, Bool)
func1 x (se, b)
  | not b = (se, b)
  | IntSet.disjoint a se = (IntSet.union se a, b)
  | otherwise = (se, False)
  where
    a = primeFactorsSet x
-------------------------------------------------------------------------------
pSpin :: Num int => int -> [int] -> [int]
pSpin x (y:ys) = x : pSpin (x + y) ys

type PWheel int      = ([int], [int])
data PQueue int
  = Empty
  | Fork [int] [PQueue int]
type PComposites int = (PQueue int, [[int]])

pEnqueue :: Ord int => [int] -> PQueue int -> PQueue int
pEnqueue ns = pMerge (Fork ns [])

pMergeAll :: Ord int => [PQueue int] -> PQueue int
pMergeAll []       = Empty
pMergeAll [x]      = x
pMergeAll (x:y:qs) = pMerge (pMerge x y) (pMergeAll qs)

pDequeue :: Ord int => PQueue int -> ([int], PQueue int)
pDequeue (Fork ns qs) = (ns, pMergeAll qs)

pMerge :: Ord int => PQueue int -> PQueue int -> PQueue int
pMerge Empty y    = y
pMerge x Empty    = x
pMerge x y
  | prio x <= prio y = join x y
  | otherwise        = join y x
  where
    prio (Fork (n:_) _) = n
    join (Fork ns qs) q = Fork ns (q:qs)

pDiscard :: Ord int => int -> PComposites int -> PComposites int
pDiscard n ns
  | n == m    = pDiscard n ms
  | otherwise = ns
  where
    (m, ms) = pSplitComposites ns

pSplitComposites :: Ord int => PComposites int -> (int, PComposites int)
pSplitComposites (Empty, xs:xss) = pSplitComposites (Fork xs [], xss)
pSplitComposites (queue, xss@((x:xs):yss))
  | x < z     = (x, pDiscard x (pEnqueue xs queue, yss))
  | otherwise = (z, pDiscard z (pEnqueue zs queue', xss))
  where
    (z:zs, queue') = pDequeue queue

pSieveComps :: (Ord int, Num int) => int -> [int] -> PComposites int -> [[int]]
pSieveComps cand ns@(m:ms) xs
  | cand == comp = pSieveComps (cand+m) ms ys
  | cand <  comp = pSpin cand ns : pSieveComps (cand + m) ms xs
  | otherwise    = pSieveComps cand ns ys
  where
    (comp, ys) = pSplitComposites xs

pComposites :: (Ord int, Num int) => int -> [int] -> PComposites int
pComposites p ns = (Empty, map comps (pSpin p ns: pSieve p ns))
  where
    comps xs@(x:_) = map (x*) xs

pSieve :: (Ord int, Num int) => int -> [int] -> [[int]]
pSieve p ns@(m:ms) = pSpin p ns : pSieveComps (p+m) ms (pComposites p ns)

pCancel :: Integral int => int -> int -> int -> [int] -> [int]
pCancel 0 _ _ _ = []
pCancel m p n (x:ys@(y:zs))
  | nx `mod` p > 0 = x : pCancel (m - x) p nx ys
  | otherwise      = pCancel m p n (x+y:zs)
  where
    nx = n + x

pNext :: Integral int => PWheel int -> PWheel int
pNext (ps@(p:_), xs) = (py:ps, pCancel (product ps) p py ys)
  where
    (y:ys) = cycle xs
    py = p + y

pWheel :: Integral int => Int -> PWheel int
pWheel n = iterate pNext ([2], [1]) !! n

pWheelSieve :: Integral int => Int -> [int]
pWheelSieve k = reverse ps ++ map head (pSieve p (cycle ns))
  where
    (p:ps,ns) = pWheel k

{- public -}
primeFactors :: Integral int => int -> [int]
primeFactors n = factors n (pWheelSieve 6)
  where
    factors 1 _      = []
    factors m (p:ps)
      | m < p * p = [m]
      | r == 0    = p : factors q (p:ps)
      | otherwise = factors m ps
      where
        (q, r) = quotRem m p

{- private -}
primeFactorsSet :: Int -> IntSet
primeFactorsSet n = factors n (pWheelSieve 6)
  where
    factors :: Int -> [Int] -> IntSet
    factors 1 _ = IntSet.empty
    factors m (p:ps)
      | m < p * p = IntSet.singleton m
      | r == 0    = IntSet.insert p $ factors q (p:ps)
      | otherwise = factors m ps
      where (q, r) = quotRem m p

{- public -}
primes :: Integral int => [int]
primes = pWheelSieve 6

{- public -}
isPrime :: Integral int => int -> Bool
isPrime n
  | n > 1 = primeFactors n == [n]
  | otherwise = False

{- public -}
composites :: Integral int => [int]
composites = List.unfoldr (\(a1: as@(a2: at), ps@(ph: pt)) -> Just (a1, if a2 == ph then (at, pt) else (as, ps))) ([4..], drop 2 primes)

{- public -}
nextPrimeInt :: Int -> Int
nextPrimeInt = fromInteger . nextPrimeInteger . fromIntegral

sieveUA :: Int -> ArrU.UArray Int Bool
sieveUA top = ArrST.runSTUArray $ do
  let m = (top-1) `div` 2
      r = floor . sqrt $ fromIntegral top + 1
  sieve <- ArrST.newArray (1,m) True
  forM_ [1..r `div` 2] $ \i -> do
    isPrime <- ArrST.readArray sieve i
    when isPrime $ do
      forM_ [2*i*(i+1), 2*i*(i+2)+1..m] $ \j -> do
        ArrST.writeArray sieve j False
  return sieve

{- public -}
primesToUA :: Int -> [Int]
primesToUA top = 2 : [i*2+1 | (i,True) <- ArrU.assocs $ sieveUA top]

{- public -}
prevPrimeInt :: Int -> Int
prevPrimeInt n
  | n <= 2    = -1
  | otherwise = f n
  where
    f = last2 . primesToUA
    last2 :: [a] -> a
    last2 []     = error "lack of list elements"
    last2 [x]    = error "lack of list elements"
    last2 [x,y]  = x
    last2 (x:xs) = last2 xs

{- public -}
millerRabin :: Int -> Bool
millerRabin n
  |  n <= 1 = False
  |  n == 2
  || n == 3
  || n == 5
  || n == 7 = True
  |  even n = False
  |  otherwise = mrCheck $ fromIntegral n
powerMR :: Integer -> Integer -> Integer -> Integer
powerMR b e m = loop 1 (b `mod` m) e
  where
    loop res base pxe
      | pxe <= 0 = res
      | otherwise =
        let res'  = if pxe `mod` 2 == 1 then (res * base) `mod` m else res
            pxe'  = shift pxe (-1)
            base' = (base * base) `mod` m
        in loop res' base' pxe'
factoringPowers :: Integer -> (Integer, Integer)
factoringPowers n = loop (n - 1) 0
  where
    loop d s
      | even d    = loop (d `div` 2) (s + 1)
      | otherwise = (s, d)
mrCheck :: Integer -> Bool
mrCheck p
  | p < 2047                = loop [2]
  | p < 9080191             = loop [31,73]
  | p < 4759123141          = loop [2,7,61]
  | p < 1122004669633       = loop [2,13,23,1662803]
  | p < 2152302898747       = loop [2,3,5,7,11]
  | p < 341550071728321     = loop [2,3,5,7,11,13,17]
  | p < 3825123056546413051 = loop [2,3,5,7,11,13,17,19,23]
  | p < 9223372036854775808 = loop [2,325,9375,28178,450775,9780504,1795265022]
  | otherwise               = loop [ 2 .. min (p - 1) (floor $ 2 * (log p')^(2 :: Int)) ]
  where
    p' = fromIntegral p :: Double
    (s, d) = factoringPowers p
    loop [] = True
    loop (a:as)
      | (powerMR a d p) /= 1 && powLoop 0 = False
      | otherwise = loop as
      where
        powLoop r
          | r < s     = (powerMR a (2 ^ r * d) p) /= (p - 1)  && powLoop (r + 1)
          | otherwise = True

{- public -}
totient :: Int -> Int
totient n = n `quot` List.product ps * (List.product $ map (subtract 1) ps)
  where ps = map head . List.group $ primeFactors n

{- public -}
divisor :: Int -> [Int]
divisor n = List.foldr f [] $ List.takeWhile ((<= n) . (^ 2)) [1 .. n]
  where
    f x ds
      | r == 0, q /= x = x : q : ds
      | r == 0         = x : ds
      | otherwise      = ds
      where
        (q, r) = n `divMod` x
-------------------------------------------------------------------------------
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
parse4 :: IO (Int, Int, Int, Int)
parse4 = (\vec -> (vec VU.! 0, vec VU.! 1, vec VU.! 2, vec VU.! 3)) . VU.unfoldrN 4 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
parseANBN :: Int -> IO (VU.Vector Int, VU.Vector Int)
parseANBN n = do
  vectup <- VU.replicateM n $ (\vec -> (vec VU.! 0, vec VU.! 1)) . VU.unfoldr (BSC8.readInt . BSC8.dropWhile Char.isSpace) <$> BSC8.getLine
  return $ VU.unzip vectup
parseANBNCN :: Int -> IO (VU.Vector Int, VU.Vector Int, VU.Vector Int)
parseANBNCN n = do
  vectup <- VU.replicateM n $ (\vec -> (vec VU.! 0, vec VU.! 1, vec VU.! 2)) . VU.unfoldr (BSC8.readInt . BSC8.dropWhile Char.isSpace) <$> BSC8.getLine
  return $ VU.unzip3 vectup

Score : 500 points

Problem Statement

We have N integers. The i-th number is A_i.

\{A_i\} is said to be pairwise coprime when GCD(A_i,A_j)=1 holds for every pair (i, j) such that 1\leq i < j \leq N.

\{A_i\} is said to be setwise coprime when \{A_i\} is not pairwise coprime but GCD(A_1,\ldots,A_N)=1.

Determine if \{A_i\} is pairwise coprime, setwise coprime, or neither.

Here, GCD(\ldots) denotes greatest common divisor.

Constraints

2 \leq N \leq 10^6

1 \leq A_i\leq 10^6

Input

Input is given from Standard Input in the following format:

N
A_1 \ldots A_N

Output

If \{A_i\} is pairwise coprime, print pairwise coprime; if \{A_i\} is setwise coprime, print setwise coprime; if neither, print not coprime.

Sample Input 1

3
3 4 5

Sample Output 1

pairwise coprime

GCD(3,4)=GCD(3,5)=GCD(4,5)=1, so they are pairwise coprime.

Sample Input 2

3
6 10 15

Sample Output 2

setwise coprime

Since GCD(6,10)=2, they are not pairwise coprime. However, since GCD(6,10,15)=1, they are setwise coprime.

Sample Input 3

3
6 10 16

Sample Output 3

not coprime

GCD(6,10,16)=2, so they are neither pairwise coprime nor setwise coprime.


{-# LANGUAGE MultiWayIf #-}

module Main where

import           Control.Monad
import           Control.Monad.Extra
import qualified Data.Array as A
import qualified Data.Array.IO as AIO
import qualified Data.Array.Unboxed as AU
--import qualified Data.Heap                     as H
import           Data.Bits
import           Data.Bool
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BSC8
import           Data.Char
import           Data.Either
import           Data.Function
import qualified Data.Graph.Inductive.Graph as G
import qualified Data.Graph.Inductive.PatriciaTree as G
import           Data.Int
import           Data.List
import qualified Data.Map.Strict as M
import           Data.Maybe
import           Data.Monoid
import           Data.Ord
import qualified Data.Sequence as SQ
import qualified Data.Set as S
import           Data.Tuple
import qualified Data.Vector as V
import           Data.Vector.Algorithms.Search
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import           Debug.Trace

main = do
  --aN       <- getI
  --[aA, aB] <- getIL
  --aS       <- getLine
  aN <- getI
  aA <- getVUI
  let maxiA = VU.maximum aA
  osaKTable <- osaKMethod (maxiA)
  hist <- VUM.replicate (maxiA + 1) False :: IO (VUM.IOVector Bool)
  histInsert hist (getPrimes osaKTable (VU.head aA))
  bbb@(ddd, eee) <- myVUfoldM
    (\acc@(flg, ccc) x
     -> if flg
        then if x == 1
             then return $ Left (True, 1)
             else do
               let primes1 = getPrimes osaKTable x
               histTrue <- histMember hist primes1
               if histTrue
                 then return $ Left (False, gcd ccc x)
                 else do
                   histInsert hist primes1
                   return $ Left (True, 1)
        else if ccc == 1
             then return $ Right (False, 1)
             else return $ Left (False, gcd ccc x))
    (True, VU.head aA)
    (VU.tail aA)
  putStrLn
    $ if
      | ddd -> "pairwise coprime"
      | eee == 1 -> "setwise coprime"
      | otherwise -> "not coprime"
  return ()

myVUfoldM f acc vu =
  if vu == VU.empty
  then return acc
  else do
    ret <- f acc (VU.head vu)
    if isLeft ret
      then myVUfoldM f (either id id ret) (VU.tail vu)
      else return $ either id id ret

histInsert hist primes = VU.mapM (\x -> VUM.write hist x True) primes

histMember hist primes = do
  myVUfoldM
    (\acc x -> do
       target <- VUM.read hist x :: IO (Bool)
       if target
         then return $ Right True
         else return $ Left False)
    False
    primes

getPrimes aaa x = VU.unfoldr
  (\y -> let (prime, quo) = getPrimesP aaa y
         in if y == 1
            then Nothing
            else Just (prime, quo))
  x

getPrimesP aaa x = let target = aaa VU.! x
                   in if target == 0
                      then (x, 1)
                      else (target, div x target)

{-
hMaxPoint :: Int
hMaxPoint = 101
hMaximum :: H.Heap Int -> Int
hMaximum h = hMaxPoint - (H.minimum h)
hInsertMax :: Int -> H.Heap Int -> H.Heap Int
hInsertMax x = H.insert (hMaxPoint - x)
hDeleteMax :: H.Heap Int -> H.Heap Int
hDeleteMax = H.deleteMin
-}
{-}
aroundSquare y x h w =
  [ aYX
    | aYX@(aY, aX) <- [(y - 1, x), (y, x - 1), (y + 1, x), (y, x + 1), (y, x)],
      aY >= 0,
      aY <= (h - 1),
      aX >= 0,
      aX <= (w - 1)
  ]
-}
aroundSquare y x h w =
  [aYX
  | aYX@(aY, aX)
      <- [(y + a, x + b) | a <- [-1 .. 1], b <- [-1 .. 1], abs a + abs b == 1]
  , aY >= 1
  , aY <= h
  , aX >= 1
  , aX <= w
  , (aY /= y) || (aX /= x)]

splitReadBSC8 :: BSC8.ByteString -> [Int]
splitReadBSC8 bs = let (bs1, newBs) = BSC8.splitAt 1 bs
                   in if newBs == BSC8.empty
                      then [test $ BSC8.readInt bs1]
                      else test (BSC8.readInt bs1):splitReadBSC8 newBs
  where
    test (Just (i, _)) = i

read2DimChar :: VM.IOVector (VUM.IOVector Char) -> Int -> Int -> IO Char
read2DimChar vec y x = do
  vecY <- VM.read vec y
  VUM.read vecY x

write2DimChar :: VM.IOVector (VUM.IOVector Char) -> Int -> Int -> Char -> IO ()
write2DimChar vec y x t = do
  vecY <- VM.read vec y
  VUM.write vecY x t

readTwoDimVec :: VM.IOVector (VUM.IOVector Int) -> Int -> Int -> IO Int
readTwoDimVec vec y x = do
  vecY <- VM.read vec y
  VUM.read vecY x

writeTwoDimVec :: VM.IOVector (VUM.IOVector Int) -> Int -> Int -> Int -> IO ()
writeTwoDimVec vec y x t = do
  vecY <- VM.read vec y
  VUM.write vecY x t

getVUI :: IO (VU.Vector Int)
getVUI = VU.unfoldr (BSC8.readInt . BSC8.dropWhile isSpace) <$> BSC8.getLine

getRepVUI :: Int -> IO (VU.Vector Int)
getRepVUI n = VU.unfoldr (BSC8.readInt . BSC8.dropWhile isSpace) . BSC8.unlines
  <$> replicateM n BSC8.getLine

getVS :: IO (V.Vector Char)
getVS = V.fromList <$> getLine

getVUC :: IO (VU.Vector Char)
getVUC = VU.fromList <$> getLine

readI :: BSC8.ByteString -> Int
readI = fst . fromJust . BSC8.readInt

readIL :: BSC8.ByteString -> [Int]
readIL = map readI . BSC8.words

readIT2 :: BSC8.ByteString -> (Int, Int)
readIT2 bs = let words = BSC8.words bs
             in (readI $ head words, readI $ last words)

getI :: IO Int
getI = readI <$> BSC8.getLine

getIL :: IO [Int]
getIL = readIL <$> BSC8.getLine

getIT2 :: IO (Int, Int)
getIT2 = readIT2 <$> BSC8.getLine

getIT2Order :: IO (Int, Int)
getIT2Order = getIL
  >>= \x@[xz, xo] -> if xz > xo
                     then return (xo, xz)
                     else return (xz, xo)

getNIS :: Int -> IO [(Int, BSC8.ByteString)]
getNIS 0 = return []
getNIS n = do
  [aFst, aSnd] <- BSC8.words <$> BSC8.getLine
  next <- getNIS (n - 1)
  return ((readI aFst, aSnd):next)

il2Words :: [Int] -> String
il2Words = unwords . map show

il2Lines :: [Int] -> String
il2Lines = unlines . map show

p :: Int -> Int
p x = x - 1

--modNum = 10 ^ 9 + 7
--modulus = 1000000007
modulus = 1000000007

newtype MInt = M Int

instance Num MInt where
  (M a) + (M b) = M $ mod (a + b) modulus

  (M a) - (M b) = M $ mod (a - b) modulus

  (M a) * (M b) = M $ mod (a * b) modulus

  fromInteger a = M $ mod (fromInteger a) modulus

  abs (M a) = undefined

  signum (M a) = undefined

instance Show MInt where
  show (M a) = show (mod a modulus)

int2MInt :: Int -> MInt
int2MInt a = M (mod a modulus)

mInt2Int :: MInt -> Int
mInt2Int (M a) = a

{-
factsMod :: V.Vector MInt
factsMod = V.scanl (\acc x -> M x * acc) 1 $ V.generate 2000000 (+ 1)

factMod :: Int -> MInt
factMod = (factsMod V.!)
-}
factMod :: Int -> MInt
factMod n
  | n == 0 = 1
  | n == 1 = 1
  | otherwise = M n * factMod (n - 1)

factDivMod :: Int -> Int -> MInt
factDivMod n k
  | n == k = M 1
  | otherwise = M n * factDivMod (n - 1) k

powMod :: MInt -> MInt -> MInt
powMod n mK@(M k)
  | k == 0 = M 1
  | k == 1 = n
  | mod k 2 == 0 = powMod (n ^ 2) (M (div k 2))
  | otherwise = n * powMod (n ^ 2) (M (div k 2))

invMod :: MInt -> MInt
invMod (M 0) = error "inverse of 0"
invMod x = powMod x (M (modulus - 2))

{-
combiMod :: Int -> Int -> MInt
combiMod n k
  | n < 0 || k < 0 || k > n = 0
  | otherwise = factMod n * invMod (factMod (n - k)) * invMod (factMod k)
-}
combiMod :: Int -> Int -> MInt
combiMod n k
  | n < 0 || k < 0 || k > n = 0
  | k > n - k = factDivMod n k * invMod (factMod (n - k))
  | otherwise = factDivMod n (n - k) * invMod (factMod k)

combi :: Int -> Int -> Int
combi n k
  | n < 0 || k < 0 || k > n = 0
  | k == n = 1
  | otherwise = div (div (fact n) (fact (n - k))) (fact k)

{-w
primes :: Integral a => [a]
primes = map fromIntegral $ [2, 3] ++ primes'
 where
  primes' = [5] ++ f 1 7 primes'
  f m s (p : ps) = [ n | n <- ns, gcd m n == 1 ] ++ f (m * p) (p * p) ps
    where ns = [ x + y | x <- [s, s + 6 .. p * p - 2], y <- [0, 4] ]

prime n = primes !! n
primes = sieve [2 ..]
sieve (p : xs) = p : sieve [ x | x <- xs, x `mod` p /= 0 ]
-}
fact :: Int -> Int
fact 0 = 1
fact n
  | n > 0 = n * fact (n - 1)

knappsackWDP :: Int -> [(Int, Int)] -> VU.Vector Int
knappsackWDP maxW [] = VU.replicate (maxW + 1) 0
knappsackWDP maxW ((w, v):xs) =
  let tailDP = knappsackWDP maxW xs
  in VU.generate (maxW + 1)
     $ \i -> if w <= i
             then max (tailDP VU.! i) (tailDP VU.! (i - w) + v)
             else tailDP VU.! i

knappsackVDP :: Int -> Int -> Int -> [(Int, Int)] -> VU.Vector Int
knappsackVDP maxW maxV n [] = VU.cons 0 $ VU.replicate (n * maxV) maxW
knappsackVDP maxW maxV n ((w, v):xs) =
  let tailDP = knappsackVDP maxW maxV n xs
  in VU.generate (n * maxV + 1)
     $ \i -> if v <= i
             then min (tailDP VU.! i) (tailDP VU.! (i - v) + w)
             else tailDP VU.! i

knappsackMinVol :: AIO.IOArray (Int, Int) Int
                -> VU.Vector Int
                -> VU.Vector Int
                -> Int
                -> Int
                -> IO Int
knappsackMinVol dp volumeVec valueVec dpSize maxVolume = do
  mapM_
    (\i -> mapM_
       (\v -> do
          let volume = volumeVec VU.! i
              value = valueVec VU.! i
          newdp <- if (v + value) > dpSize
                   then AIO.readArray dp (i, v)
                   else do
                     dpIVm <- AIO.readArray dp (i, v + value)
                     dpIV <- AIO.readArray dp (i, v)
                     return (min (dpIVm - volume) dpIV)
          AIO.writeArray dp (i + 1, v) newdp)
       (reverse [0 .. dpSize]))
    [0 .. VU.length valueVec - 1]
  foldM
    (\acc x -> do
       num <- AIO.readArray dp (VU.length volumeVec, x)
       return
         $ if num <= maxVolume
           then x
           else acc)
    0
    [0 .. dpSize]

lcsTable :: BS.ByteString -> BS.ByteString -> V.Vector (VU.Vector Int)
lcsTable xs ys = V.scanl step (VU.replicate (m + 1) 0) xs'
  where
    n = BS.length xs

    m = BS.length ys

    xs' = V.generate n $ BSC8.index xs :: V.Vector Char

    ys' = VU.generate m $ BSC8.index ys :: VU.Vector Char

    step :: VU.Vector Int -> Char -> VU.Vector Int
    step v x = VU.scanl innerStep 0 (VU.zip3 v (VU.tail v) ys')
      where
        innerStep :: Int -> (Int, Int, Char) -> Int
        innerStep a (b, c, y)
          | x == y = 1 + b
          | otherwise = max a c

{-
main = do
xs <- BS.getLine
ys <- BS.getLine
print $ VU.last $ V.last $ lcsTable xs ys
-}
myFilter :: (a -> Bool) -> [a] -> ([a], [a])
myFilter _pred [] = ([], [])
myFilter pred (x:xs)
  | pred x = let (l, r) = myFilter pred xs
             in (x:l, r)
  | otherwise = let (l, r) = myFilter pred xs
                in (l, x:r)

--UnionFindデータ構造
type UF_PARENT = VUM.IOVector Int

type UF_RANK = VUM.IOVector Int

type UF = (UF_PARENT, UF_RANK)

ufMakeSet :: Int -> IO UF
ufMakeSet n = do
  parent <- VU.thaw $ VU.generate n id
  rank <- VUM.replicate n 0
  return (parent, rank)

ufUnion :: UF -> Int -> Int -> IO ()
ufUnion unionFind@(parents, ranks) x y = do
  xRoot <- ufFind unionFind x
  yRoot <- ufFind unionFind y
  xRootRank <- VUM.read ranks xRoot
  yRootRank <- VUM.read ranks yRoot
  if
    | xRootRank > yRootRank -> VUM.write parents yRoot xRoot
    | xRootRank < yRootRank -> VUM.write parents xRoot yRoot
    | xRoot /= yRoot -> do
      VUM.write parents yRoot xRoot
      VUM.write ranks xRoot (xRootRank + 1)
    | otherwise -> return ()

ufFind :: UF -> Int -> IO Int
ufFind unionFind@(parents, ranks) x = do
  xParent <- VUM.read parents x
  if xParent == x
    then return x
    else do
      xRootParent <- ufFind unionFind xParent
      VUM.write parents x xRootParent
      return xRootParent

--UnDirectedGraph(無向グラフ)データ構造
type UDG = M.Map Int [Int]

list2UDG :: [(Int, Int)] -> M.Map Int [Int]
list2UDG = foldl
  (\acc x -> let lr = M.insertWith (++) (fst x) [snd x] acc
             in M.insertWith (++) (snd x) [fst x] lr)
  M.empty

--OSA-K法テーブル準備(お酒？)
osaKMethod m = do
  table <- VUM.replicate (m + 1) (0 :: Int) :: IO (VUM.IOVector Int)
  modi table m 2 1 1 (div m 2)
  loopModi table m 3
  VU.freeze table
  where
    loopModi table m x
      | x > m = return ()
      | otherwise = do
        modi table m x 1 2 (div m x)
        loopModi table m (x + 2)

    modi table m x n s nm
      | n > nm = return ()
      | otherwise = do
        let xn = x * n
        target <- VUM.read table xn
        if target == 0
          then do
            VUM.write table xn x
            modi table m x (n + s) s nm
          else if n == 1
               then return ()
               else modi table m x (n + s) s nm


{-# LANGUAGE MultiWayIf #-}

module Main where

import Control.Monad
import Control.Monad.Extra
import qualified Data.Array as A
import qualified Data.Array.IO as AIO
import qualified Data.Array.Unboxed as AU
--import qualified Data.Heap                     as H

import Data.Bits
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BSC8
import Data.Char
import qualified Data.Graph.Inductive.Graph as G
import qualified Data.Graph.Inductive.PatriciaTree as G
import Data.Int
import Data.List
import qualified Data.Map.Strict as M
import Data.Maybe
import Data.Monoid
import Data.Ord
import qualified Data.Sequence as SQ
import qualified Data.Set as S
import qualified Data.Vector as V
import Data.Vector.Algorithms.Search
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import Debug.Trace
import Prelude

main =
  do
    --aN       <- getI
    --[aA, aB] <- getIL
    --aS       <- getLine

    aN <- getI
    aA <- getIL

    aaa <- era
    bbb@(ddd, eee, _) <-
      foldM
        ( \acc@(flg, ccc, hist) x ->
            if flg == True
              then do
                let primes1 = primes aaa x
                if histMember primes1 hist
                  then return (False, gcd ccc x, hist)
                  else return (True, gcd ccc x, histInsert primes1 hist)
              else return (False, gcd ccc x, hist)
        )
        (True, head aA, histInsert (primes aaa (head aA)) S.empty)
        (tail aA)

    if ddd == True
      then putStrLn "pairwise coprime"
      else
        if eee == 1
          then putStrLn "setwise coprime"
          else putStrLn "not coprime"
    return ()

histInsert primes hist =
  foldl ((flip S.insert)) hist primes

histMember [] hist = False
histMember (prime : primes) hist =
  if S.member prime hist
    then True
    else histMember primes hist

primes aaa x
  | x == 0 || x == 1 = []
  | otherwise =
    let (prime, quo) = primesP aaa x
     in if quo == 1
          then [prime]
          else prime : (primes aaa quo)

primesP aaa x =
  let target = aaa VU.! x
   in if target == 0
        then (x, 1)
        else (target, div x target)

era = do
  aaa <- VUM.replicate (10 ^ 6 + 1) (0 :: Int) :: IO (VUM.IOVector Int)
  eraP aaa 2
  mapM_ (\y -> eraP aaa y) [x * 2 + 1 | x <- [1 .. 500000]]
  VU.freeze aaa

eraP aaa x
  | x > 1000000 = return ()
  | otherwise = modi aaa x 1

modi aaa x n
  | x * n > 1000000 = return ()
  | otherwise = do
    target <- VUM.read aaa (x * n)
    if target == 0
      then do
        VUM.write aaa (x * n) x
        modi aaa x (n + 1)
      else modi aaa x (n + 1)

{-
hMaxPoint :: Int
hMaxPoint = 101
hMaximum :: H.Heap Int -> Int
hMaximum h = hMaxPoint - (H.minimum h)
hInsertMax :: Int -> H.Heap Int -> H.Heap Int
hInsertMax x = H.insert (hMaxPoint - x)
hDeleteMax :: H.Heap Int -> H.Heap Int
hDeleteMax = H.deleteMin
-}
{-}
aroundSquare y x h w =
  [ aYX
    | aYX@(aY, aX) <- [(y - 1, x), (y, x - 1), (y + 1, x), (y, x + 1), (y, x)],
      aY >= 0,
      aY <= (h - 1),
      aX >= 0,
      aX <= (w - 1)
  ]
-}

aroundSquare y x h w =
  [ aYX
    | aYX@(aY, aX) <- [(y + a, x + b) | a <- [-1 .. 1], b <- [-1 .. 1], abs (a) + abs (b) == 1],
      aY >= 1,
      aY <= (h),
      aX >= 1,
      aX <= (w),
      (aY /= y) || (aX /= x)
  ]

warpAroundSquare y x h w =
  [ aYX
    | aYX@(aY, aX) <- [(y + a, x + b) | a <- [-2 .. 2], b <- [-2 .. 2], abs (a) + abs (b) > 1],
      aY >= 1,
      aY <= (h),
      aX >= 1,
      aX <= (w),
      (aY /= y) || (aX /= x)
  ]

splitReadBSC8 :: BSC8.ByteString -> [Int]
splitReadBSC8 bs =
  let (bs1, newBs) = BSC8.splitAt 1 bs
   in if newBs == BSC8.empty
        then [test $ BSC8.readInt bs1]
        else (test $ BSC8.readInt bs1) : (splitReadBSC8 newBs)
  where
    test (Just (i, _)) = i

read2DimChar :: VM.IOVector (VUM.IOVector Char) -> Int -> Int -> IO Char
read2DimChar vec y x = do
  vecY <- VM.read vec y
  VUM.read vecY x

write2DimChar :: VM.IOVector (VUM.IOVector Char) -> Int -> Int -> Char -> IO ()
write2DimChar vec y x t = do
  vecY <- VM.read vec y
  VUM.write vecY x t

readTwoDimVec :: VM.IOVector (VUM.IOVector Int) -> Int -> Int -> IO Int
readTwoDimVec vec y x = do
  vecY <- VM.read vec y
  VUM.read vecY x

writeTwoDimVec :: VM.IOVector (VUM.IOVector Int) -> Int -> Int -> Int -> IO ()
writeTwoDimVec vec y x t = do
  vecY <- VM.read vec y
  VUM.write vecY x t

getVUI :: IO (VU.Vector Int)
getVUI = VU.unfoldr (BSC8.readInt . BSC8.dropWhile isSpace) <$> BSC8.getLine

getRepVUI :: Int -> IO (VU.Vector Int)
getRepVUI n =
  VU.unfoldr (BSC8.readInt . BSC8.dropWhile isSpace)
    . BSC8.unlines
    <$> replicateM n BSC8.getLine

getVS :: IO (V.Vector Char)
getVS = V.fromList <$> getLine

getVUC :: IO (VU.Vector Char)
getVUC = VU.fromList <$> getLine

readI :: BSC8.ByteString -> Int
readI = fst . fromJust . BSC8.readInt

readIL :: BSC8.ByteString -> [Int]
readIL = map readI . BSC8.words

readIT2 :: BSC8.ByteString -> (Int, Int)
readIT2 bs =
  let words = BSC8.words bs in (readI $ head words, readI $ last words)

getI :: IO Int
getI = readI <$> BSC8.getLine

getIL :: IO [Int]
getIL = readIL <$> BSC8.getLine

getIT2 :: IO (Int, Int)
getIT2 = readIT2 <$> BSC8.getLine

getIT2Order :: IO (Int, Int)
getIT2Order =
  getIL
    >>= \x@[xz, xo] -> if xz > xo then return (xo, xz) else return (xz, xo)

getNIS :: Int -> IO [(Int, BSC8.ByteString)]
getNIS 0 = return []
getNIS n = do
  [aFst, aSnd] <- BSC8.words <$> BSC8.getLine
  next <- getNIS (n - 1)
  return ((readI aFst, aSnd) : next)

il2Words :: [Int] -> String
il2Words = unwords . map show

il2Lines :: [Int] -> String
il2Lines = unlines . map show

p :: Int -> Int
p x = x - 1

--modNum = 10 ^ 9 + 7
--modulus = 1000000007
modulus = 1000000007

newtype MInt = M Int

instance Num MInt where
  (M a) + (M b) = M $ mod (a + b) modulus

  (M a) - (M b) = M $ mod (a - b) modulus

  (M a) * (M b) = M $ mod (a * b) modulus

  fromInteger a = M $ mod (fromInteger a) modulus

  abs (M a) = undefined

  signum (M a) = undefined

instance Show MInt where
  show (M a) = show (mod a modulus)

int2MInt :: Int -> MInt
int2MInt a = M (mod a modulus)

mInt2Int :: MInt -> Int
mInt2Int (M a) = a

{-
factsMod :: V.Vector MInt
factsMod = V.scanl (\acc x -> M x * acc) 1 $ V.generate 2000000 (+ 1)

factMod :: Int -> MInt
factMod = (factsMod V.!)
-}

factMod :: Int -> MInt
factMod n
  | n == 0 = 1
  | n == 1 = 1
  | otherwise = M n * (factMod (n - 1))

factDivMod :: Int -> Int -> MInt
factDivMod n k
  | n == k = M 1
  | otherwise = M n * (factDivMod (n - 1) k)

powMod :: MInt -> MInt -> MInt
powMod n mK@(M k)
  | k == 0 = M 1
  | k == 1 = n
  | mod k 2 == 0 = powMod (n ^ 2) (M (div k 2))
  | otherwise = n * powMod (n ^ 2) (M (div k 2))

invMod :: MInt -> MInt
invMod (M 0) = error "inverse of 0"
invMod x = powMod x (M (modulus - 2))

{-
combiMod :: Int -> Int -> MInt
combiMod n k
  | n < 0 || k < 0 || k > n = 0
  | otherwise = factMod n * invMod (factMod (n - k)) * invMod (factMod k)
-}
combiMod :: Int -> Int -> MInt
combiMod n k
  | n < 0 || k < 0 || k > n = 0
  | k > n - k = factDivMod n k * invMod (factMod (n - k))
  | otherwise = factDivMod n (n - k) * invMod (factMod k)

combi :: Int -> Int -> Int
combi n k
  | n < 0 || k < 0 || k > n = 0
  | k == n = 1
  | otherwise = div (div (fact n) (fact (n - k))) (fact k)

{-w
primes :: Integral a => [a]
primes = map fromIntegral $ [2, 3] ++ primes'
 where
  primes' = [5] ++ f 1 7 primes'
  f m s (p : ps) = [ n | n <- ns, gcd m n == 1 ] ++ f (m * p) (p * p) ps
    where ns = [ x + y | x <- [s, s + 6 .. p * p - 2], y <- [0, 4] ]

prime n = primes !! n
primes = sieve [2 ..]
sieve (p : xs) = p : sieve [ x | x <- xs, x `mod` p /= 0 ]
-}
fact :: Int -> Int
fact 0 = 1
fact n | n > 0 = n * fact (n - 1)

knappsackWDP :: Int -> [(Int, Int)] -> VU.Vector Int
knappsackWDP maxW [] = VU.replicate (maxW + 1) 0
knappsackWDP maxW ((w, v) : xs) =
  let tailDP = knappsackWDP maxW xs
   in VU.generate (maxW + 1) $ \i ->
        if w <= i
          then max (tailDP VU.! i) (tailDP VU.! (i - w) + v)
          else tailDP VU.! i

knappsackVDP :: Int -> Int -> Int -> [(Int, Int)] -> VU.Vector Int
knappsackVDP maxW maxV n [] = VU.cons 0 $ VU.replicate (n * maxV) maxW
knappsackVDP maxW maxV n ((w, v) : xs) =
  let tailDP = knappsackVDP maxW maxV n xs
   in VU.generate (n * maxV + 1) $ \i ->
        if v <= i
          then min (tailDP VU.! i) (tailDP VU.! (i - v) + w)
          else tailDP VU.! i

knappsackMinVol ::
  AIO.IOArray (Int, Int) Int ->
  VU.Vector Int ->
  VU.Vector Int ->
  Int ->
  Int ->
  IO Int
knappsackMinVol dp volumeVec valueVec dpSize maxVolume = do
  mapM_
    ( \i ->
        mapM_
          ( \v -> do
              let volume = volumeVec VU.! i
                  value = valueVec VU.! i
              newdp <-
                if (v + value) > dpSize
                  then AIO.readArray dp (i, v)
                  else do
                    dpIVm <- AIO.readArray dp (i, v + value)
                    dpIV <- AIO.readArray dp (i, v)
                    return (min (dpIVm - volume) dpIV)
              AIO.writeArray dp (i + 1, v) newdp
          )
          (reverse [0 .. dpSize])
    )
    [0 .. VU.length valueVec - 1]
  foldM
    ( \acc x -> do
        num <- AIO.readArray dp (VU.length volumeVec, x)
        return $ if num <= maxVolume then x else acc
    )
    0
    [0 .. dpSize]

lcsTable :: BS.ByteString -> BS.ByteString -> V.Vector (VU.Vector Int)
lcsTable xs ys = V.scanl step (VU.replicate (m + 1) 0) xs'
  where
    n = BS.length xs
    m = BS.length ys
    xs' = V.generate n $ BSC8.index xs :: V.Vector Char
    ys' = VU.generate m $ BSC8.index ys :: VU.Vector Char
    step :: VU.Vector Int -> Char -> VU.Vector Int
    step v x = VU.scanl innerStep 0 (VU.zip3 v (VU.tail v) ys')
      where
        innerStep :: Int -> (Int, Int, Char) -> Int
        innerStep a (b, c, y)
          | x == y = 1 + b
          | otherwise = max a c

{-
main = do
xs <- BS.getLine
ys <- BS.getLine
print $ VU.last $ V.last $ lcsTable xs ys
-}

myFilter :: (a -> Bool) -> [a] -> ([a], [a])
myFilter _pred [] = ([], [])
myFilter pred (x : xs)
  | pred x = let (l, r) = myFilter pred xs in (x : l, r)
  | otherwise = let (l, r) = myFilter pred xs in (l, x : r)

--UnionFindデータ構造

type UF_PARENT = VUM.IOVector Int

type UF_RANK = VUM.IOVector Int

type UF = (UF_PARENT, UF_RANK)

uf_makeSet :: Int -> IO UF
uf_makeSet n = do
  parent <- VU.thaw $ VU.generate n id
  rank <- VUM.replicate n 0
  return (parent, rank)

uf_union :: UF -> Int -> Int -> IO ()
uf_union unionFind@(parents, ranks) x y = do
  xRoot <- uf_find unionFind x
  yRoot <- uf_find unionFind y

  xRootRank <- VUM.read ranks xRoot
  yRootRank <- VUM.read ranks yRoot
  if
      | xRootRank > yRootRank -> VUM.write parents yRoot xRoot
      | xRootRank < yRootRank -> VUM.write parents xRoot yRoot
      | xRoot /= yRoot -> do
        VUM.write parents yRoot xRoot
        VUM.write ranks xRoot (xRootRank + 1)
      | otherwise -> return ()

uf_find :: UF -> Int -> IO Int
uf_find unionFind@(parents, ranks) x = do
  xParent <- VUM.read parents x
  if xParent == x
    then return x
    else do
      xRootParent <- uf_find unionFind xParent
      VUM.write parents x xRootParent
      return xRootParent

--UnDirectedGraph(無向グラフ)データ構造

type UDG = M.Map Int [Int]

list2UDG :: [(Int, Int)] -> M.Map Int [Int]
list2UDG =
  foldl
    ( \acc x ->
        let lr = M.insertWith (++) (fst x) [snd x] acc
         in M.insertWith (++) (snd x) [fst x] lr
    )
    M.empty


{-# LANGUAGE MultiWayIf #-}

module Main where

import Control.Monad
import Control.Monad.Extra
import qualified Data.Array as A
import qualified Data.Array.IO as AIO
import qualified Data.Array.Unboxed as AU
--import qualified Data.Heap                     as H

import Data.Bits
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BSC8
import Data.Char
import qualified Data.Graph.Inductive.Graph as G
import qualified Data.Graph.Inductive.PatriciaTree as G
import Data.Int
import Data.List
import qualified Data.Map.Strict as M
import Data.Maybe
import Data.Monoid
import Data.Ord
import qualified Data.Sequence as SQ
import qualified Data.Set as S
import qualified Data.Vector as V
import Data.Vector.Algorithms.Search
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import Debug.Trace
import Prelude

main =
  do
    --aN       <- getI
    --[aA, aB] <- getIL
    --aS       <- getLine

    aN <- getI
    aA <- getIL

    aaa <- era
    bbb@(ddd, eee, _) <-
      foldM
        ( \acc@(flg, ccc, hist) x ->
            if flg == True
              then do
                let primes1 = primes aaa x
                if histMember primes1 hist
                  then return (False, gcd ccc x, hist)
                  else return (True, gcd ccc x, histInsert primes1 hist)
              else return (False, gcd ccc x, hist)
        )
        (True, head aA, histInsert (primes aaa (head aA)) S.empty)
        (tail aA)

    if ddd == True
      then putStrLn "pairwise coprime"
      else
        if eee == 1
          then putStrLn "setwise coprime"
          else putStrLn "not coprime"
    return ()

histInsert primes hist =
  foldl ((flip S.insert)) hist primes

histMember [] hist = False
histMember (prime : primes) hist =
  if S.member prime hist && prime /= 1
    then True
    else histMember primes hist

primes aaa x =
  let (prime, quo) = primesP aaa x
   in if quo == 1
        then [prime]
        else prime : (primes aaa quo)

primesP aaa x =
  let target = aaa VU.! x
   in if target == 0
        then (x, 1)
        else (target, div x target)

era = do
  aaa <- VUM.replicate (10 ^ 6 + 1) (0 :: Int) :: IO (VUM.IOVector Int)
  eraP aaa 2
  mapM_ (\y -> eraP aaa y) [x * 2 + 1 | x <- [1 .. 500000]]
  VU.freeze aaa

eraP aaa x
  | x > 1000000 = return ()
  | otherwise = modi aaa x 1

modi aaa x n
  | x * n > 1000000 = return ()
  | otherwise = do
    target <- VUM.read aaa (x * n)
    if target == 0
      then do
        VUM.write aaa (x * n) x
        modi aaa x (n + 1)
      else modi aaa x (n + 1)

{-
hMaxPoint :: Int
hMaxPoint = 101
hMaximum :: H.Heap Int -> Int
hMaximum h = hMaxPoint - (H.minimum h)
hInsertMax :: Int -> H.Heap Int -> H.Heap Int
hInsertMax x = H.insert (hMaxPoint - x)
hDeleteMax :: H.Heap Int -> H.Heap Int
hDeleteMax = H.deleteMin
-}
{-}
aroundSquare y x h w =
  [ aYX
    | aYX@(aY, aX) <- [(y - 1, x), (y, x - 1), (y + 1, x), (y, x + 1), (y, x)],
      aY >= 0,
      aY <= (h - 1),
      aX >= 0,
      aX <= (w - 1)
  ]
-}

aroundSquare y x h w =
  [ aYX
    | aYX@(aY, aX) <- [(y + a, x + b) | a <- [-1 .. 1], b <- [-1 .. 1], abs (a) + abs (b) == 1],
      aY >= 1,
      aY <= (h),
      aX >= 1,
      aX <= (w),
      (aY /= y) || (aX /= x)
  ]

warpAroundSquare y x h w =
  [ aYX
    | aYX@(aY, aX) <- [(y + a, x + b) | a <- [-2 .. 2], b <- [-2 .. 2], abs (a) + abs (b) > 1],
      aY >= 1,
      aY <= (h),
      aX >= 1,
      aX <= (w),
      (aY /= y) || (aX /= x)
  ]

splitReadBSC8 :: BSC8.ByteString -> [Int]
splitReadBSC8 bs =
  let (bs1, newBs) = BSC8.splitAt 1 bs
   in if newBs == BSC8.empty
        then [test $ BSC8.readInt bs1]
        else (test $ BSC8.readInt bs1) : (splitReadBSC8 newBs)
  where
    test (Just (i, _)) = i

read2DimChar :: VM.IOVector (VUM.IOVector Char) -> Int -> Int -> IO Char
read2DimChar vec y x = do
  vecY <- VM.read vec y
  VUM.read vecY x

write2DimChar :: VM.IOVector (VUM.IOVector Char) -> Int -> Int -> Char -> IO ()
write2DimChar vec y x t = do
  vecY <- VM.read vec y
  VUM.write vecY x t

readTwoDimVec :: VM.IOVector (VUM.IOVector Int) -> Int -> Int -> IO Int
readTwoDimVec vec y x = do
  vecY <- VM.read vec y
  VUM.read vecY x

writeTwoDimVec :: VM.IOVector (VUM.IOVector Int) -> Int -> Int -> Int -> IO ()
writeTwoDimVec vec y x t = do
  vecY <- VM.read vec y
  VUM.write vecY x t

getVUI :: IO (VU.Vector Int)
getVUI = VU.unfoldr (BSC8.readInt . BSC8.dropWhile isSpace) <$> BSC8.getLine

getRepVUI :: Int -> IO (VU.Vector Int)
getRepVUI n =
  VU.unfoldr (BSC8.readInt . BSC8.dropWhile isSpace)
    . BSC8.unlines
    <$> replicateM n BSC8.getLine

getVS :: IO (V.Vector Char)
getVS = V.fromList <$> getLine

getVUC :: IO (VU.Vector Char)
getVUC = VU.fromList <$> getLine

readI :: BSC8.ByteString -> Int
readI = fst . fromJust . BSC8.readInt

readIL :: BSC8.ByteString -> [Int]
readIL = map readI . BSC8.words

readIT2 :: BSC8.ByteString -> (Int, Int)
readIT2 bs =
  let words = BSC8.words bs in (readI $ head words, readI $ last words)

getI :: IO Int
getI = readI <$> BSC8.getLine

getIL :: IO [Int]
getIL = readIL <$> BSC8.getLine

getIT2 :: IO (Int, Int)
getIT2 = readIT2 <$> BSC8.getLine

getIT2Order :: IO (Int, Int)
getIT2Order =
  getIL
    >>= \x@[xz, xo] -> if xz > xo then return (xo, xz) else return (xz, xo)

getNIS :: Int -> IO [(Int, BSC8.ByteString)]
getNIS 0 = return []
getNIS n = do
  [aFst, aSnd] <- BSC8.words <$> BSC8.getLine
  next <- getNIS (n - 1)
  return ((readI aFst, aSnd) : next)

il2Words :: [Int] -> String
il2Words = unwords . map show

il2Lines :: [Int] -> String
il2Lines = unlines . map show

p :: Int -> Int
p x = x - 1

--modNum = 10 ^ 9 + 7
--modulus = 1000000007
modulus = 1000000007

newtype MInt = M Int

instance Num MInt where
  (M a) + (M b) = M $ mod (a + b) modulus

  (M a) - (M b) = M $ mod (a - b) modulus

  (M a) * (M b) = M $ mod (a * b) modulus

  fromInteger a = M $ mod (fromInteger a) modulus

  abs (M a) = undefined

  signum (M a) = undefined

instance Show MInt where
  show (M a) = show (mod a modulus)

int2MInt :: Int -> MInt
int2MInt a = M (mod a modulus)

mInt2Int :: MInt -> Int
mInt2Int (M a) = a

{-
factsMod :: V.Vector MInt
factsMod = V.scanl (\acc x -> M x * acc) 1 $ V.generate 2000000 (+ 1)

factMod :: Int -> MInt
factMod = (factsMod V.!)
-}

factMod :: Int -> MInt
factMod n
  | n == 0 = 1
  | n == 1 = 1
  | otherwise = M n * (factMod (n - 1))

factDivMod :: Int -> Int -> MInt
factDivMod n k
  | n == k = M 1
  | otherwise = M n * (factDivMod (n - 1) k)

powMod :: MInt -> MInt -> MInt
powMod n mK@(M k)
  | k == 0 = M 1
  | k == 1 = n
  | mod k 2 == 0 = powMod (n ^ 2) (M (div k 2))
  | otherwise = n * powMod (n ^ 2) (M (div k 2))

invMod :: MInt -> MInt
invMod (M 0) = error "inverse of 0"
invMod x = powMod x (M (modulus - 2))

{-
combiMod :: Int -> Int -> MInt
combiMod n k
  | n < 0 || k < 0 || k > n = 0
  | otherwise = factMod n * invMod (factMod (n - k)) * invMod (factMod k)
-}
combiMod :: Int -> Int -> MInt
combiMod n k
  | n < 0 || k < 0 || k > n = 0
  | k > n - k = factDivMod n k * invMod (factMod (n - k))
  | otherwise = factDivMod n (n - k) * invMod (factMod k)

combi :: Int -> Int -> Int
combi n k
  | n < 0 || k < 0 || k > n = 0
  | k == n = 1
  | otherwise = div (div (fact n) (fact (n - k))) (fact k)

{-w
primes :: Integral a => [a]
primes = map fromIntegral $ [2, 3] ++ primes'
 where
  primes' = [5] ++ f 1 7 primes'
  f m s (p : ps) = [ n | n <- ns, gcd m n == 1 ] ++ f (m * p) (p * p) ps
    where ns = [ x + y | x <- [s, s + 6 .. p * p - 2], y <- [0, 4] ]

prime n = primes !! n
primes = sieve [2 ..]
sieve (p : xs) = p : sieve [ x | x <- xs, x `mod` p /= 0 ]
-}
fact :: Int -> Int
fact 0 = 1
fact n | n > 0 = n * fact (n - 1)

knappsackWDP :: Int -> [(Int, Int)] -> VU.Vector Int
knappsackWDP maxW [] = VU.replicate (maxW + 1) 0
knappsackWDP maxW ((w, v) : xs) =
  let tailDP = knappsackWDP maxW xs
   in VU.generate (maxW + 1) $ \i ->
        if w <= i
          then max (tailDP VU.! i) (tailDP VU.! (i - w) + v)
          else tailDP VU.! i

knappsackVDP :: Int -> Int -> Int -> [(Int, Int)] -> VU.Vector Int
knappsackVDP maxW maxV n [] = VU.cons 0 $ VU.replicate (n * maxV) maxW
knappsackVDP maxW maxV n ((w, v) : xs) =
  let tailDP = knappsackVDP maxW maxV n xs
   in VU.generate (n * maxV + 1) $ \i ->
        if v <= i
          then min (tailDP VU.! i) (tailDP VU.! (i - v) + w)
          else tailDP VU.! i

knappsackMinVol ::
  AIO.IOArray (Int, Int) Int ->
  VU.Vector Int ->
  VU.Vector Int ->
  Int ->
  Int ->
  IO Int
knappsackMinVol dp volumeVec valueVec dpSize maxVolume = do
  mapM_
    ( \i ->
        mapM_
          ( \v -> do
              let volume = volumeVec VU.! i
                  value = valueVec VU.! i
              newdp <-
                if (v + value) > dpSize
                  then AIO.readArray dp (i, v)
                  else do
                    dpIVm <- AIO.readArray dp (i, v + value)
                    dpIV <- AIO.readArray dp (i, v)
                    return (min (dpIVm - volume) dpIV)
              AIO.writeArray dp (i + 1, v) newdp
          )
          (reverse [0 .. dpSize])
    )
    [0 .. VU.length valueVec - 1]
  foldM
    ( \acc x -> do
        num <- AIO.readArray dp (VU.length volumeVec, x)
        return $ if num <= maxVolume then x else acc
    )
    0
    [0 .. dpSize]

lcsTable :: BS.ByteString -> BS.ByteString -> V.Vector (VU.Vector Int)
lcsTable xs ys = V.scanl step (VU.replicate (m + 1) 0) xs'
  where
    n = BS.length xs
    m = BS.length ys
    xs' = V.generate n $ BSC8.index xs :: V.Vector Char
    ys' = VU.generate m $ BSC8.index ys :: VU.Vector Char
    step :: VU.Vector Int -> Char -> VU.Vector Int
    step v x = VU.scanl innerStep 0 (VU.zip3 v (VU.tail v) ys')
      where
        innerStep :: Int -> (Int, Int, Char) -> Int
        innerStep a (b, c, y)
          | x == y = 1 + b
          | otherwise = max a c

{-
main = do
xs <- BS.getLine
ys <- BS.getLine
print $ VU.last $ V.last $ lcsTable xs ys
-}

myFilter :: (a -> Bool) -> [a] -> ([a], [a])
myFilter _pred [] = ([], [])
myFilter pred (x : xs)
  | pred x = let (l, r) = myFilter pred xs in (x : l, r)
  | otherwise = let (l, r) = myFilter pred xs in (l, x : r)

--UnionFindデータ構造

type UF_PARENT = VUM.IOVector Int

type UF_RANK = VUM.IOVector Int

type UF = (UF_PARENT, UF_RANK)

uf_makeSet :: Int -> IO UF
uf_makeSet n = do
  parent <- VU.thaw $ VU.generate n id
  rank <- VUM.replicate n 0
  return (parent, rank)

uf_union :: UF -> Int -> Int -> IO ()
uf_union unionFind@(parents, ranks) x y = do
  xRoot <- uf_find unionFind x
  yRoot <- uf_find unionFind y

  xRootRank <- VUM.read ranks xRoot
  yRootRank <- VUM.read ranks yRoot
  if
      | xRootRank > yRootRank -> VUM.write parents yRoot xRoot
      | xRootRank < yRootRank -> VUM.write parents xRoot yRoot
      | xRoot /= yRoot -> do
        VUM.write parents yRoot xRoot
        VUM.write ranks xRoot (xRootRank + 1)
      | otherwise -> return ()

uf_find :: UF -> Int -> IO Int
uf_find unionFind@(parents, ranks) x = do
  xParent <- VUM.read parents x
  if xParent == x
    then return x
    else do
      xRootParent <- uf_find unionFind xParent
      VUM.write parents x xRootParent
      return xRootParent

--UnDirectedGraph(無向グラフ)データ構造

type UDG = M.Map Int [Int]

list2UDG :: [(Int, Int)] -> M.Map Int [Int]
list2UDG =
  foldl
    ( \acc x ->
        let lr = M.insertWith (++) (fst x) [snd x] acc
         in M.insertWith (++) (snd x) [fst x] lr
    )
    M.empty


import           Control.Monad
import           Control.Monad.ST
import           Data.Array
import           Data.Array.ST
import qualified Data.ByteString.Char8 as BS
import           Data.Maybe
import qualified Data.Vector           as V
import qualified Data.Vector.Mutable   as M

readInt = fst . fromJust . BS.readInt
readIntList = map readInt . BS.words
getIntList = readIntList <$> BS.getLine

main=do
    getLine
    a <- getIntList
    let cnt = runST $ do
            vec <- V.thaw $ V.replicate m 0
            forM_ a $ \ai ->
                forM_ (primeFactor ai) $ \j ->
                    M.modify vec (+1) j
            V.freeze vec
    putStrLn$
        if V.and $V.map (<=1) cnt
        then "pairwise coprime"
        else if foldl1 gcd a == 1
            then  "setwise coprime"
            else  "not coprime"
m = 10^6+1

table :: V.Vector Int
table = runST $ do
    vec <- V.thaw $ V.fromList [0..m]
    forM_ (takeWhile (\i -> i*i < m) [2..]) $ \i -> do
        arri <- M.read vec i
        when (arri >= i)$
            forM_ [i,i+i..m-1] $ \j -> do
                v <- M.read vec j
                when (v == j) $ M.write vec j i
    V.freeze vec

primeFactor :: Int -> [Int]
primeFactor 1 = []
primeFactor n = if null prev || head prev /= p
    then p:prev
    else prev
    where p = table V.! n
          prev = primeFactor (n `div` p)


import           Control.Monad
import           Control.Monad.ST
import           Data.Array
import           Data.Array.ST
import qualified Data.ByteString.Char8 as BS
import           Data.Maybe
import qualified Data.Vector           as V
import qualified Data.Vector.Mutable   as M

readInt = fst . fromJust . BS.readInt
readIntList = map readInt . BS.words
getIntList = readIntList <$> BS.getLine

main=do
    getLine
    a <- getIntList
    let cnt = runST $ do
            vec <- V.thaw $ V.replicate m 0
            forM_ a $ \ai ->
                forM_ (primeFactor ai) $ \j ->
                    M.modify vec (+1) j
            V.freeze vec
    putStrLn$
        if V.and $V.map (<=1) cnt
        then "pairwise coprime"
        else if foldl1 gcd a == 1
            then  "setwise coprime"
            else  "not coprime"
m = 10^6+1

table :: V.Vector Int
table = runST $ do
    vec <- V.thaw $ V.fromList [0..m]
    forM_ (takeWhile (\i -> i*i < m) [2..]) $ \i -> do
        arri <- M.read vec i
        when (arri >= i)$
            forM_ (takeWhile (\j -> i*j < m) [i..]) $ \j -> do
                v <- M.read vec (i*j)
                when (v == i*j) $ M.write vec (i*j) i
    V.freeze vec

primeFactor :: Int -> [Int]
primeFactor 1 = []
primeFactor n = if null prev || head prev /= p
    then p:prev
    else prev
    where p = table V.! n
          prev = primeFactor (n `div` p)


import Data.Array
import Data.Array.ST
import Control.Monad.ST
import Control.Monad
import qualified Data.ByteString.Char8 as BS
import Data.Maybe
import qualified          Data.Vector.Mutable as M
import qualified Data.Vector as V

tuplify2 (x:y:_) = (x,y)
tuplify2 _ = undefined

readInt = fst . fromJust . BS.readInt
readIntTuple = tuplify2 . map readInt . BS.words
readIntList = map readInt . BS.words

getInt = readInt <$> BS.getLine
getIntList = readIntList <$> BS.getLine
getIntNList n = map readIntList <$> replicateM (fromIntegral n) BS.getLine
getIntMatrix = map readIntList . BS.lines <$> BS.getContents
getIntTuple = readIntTuple <$> BS.getLine
getIntNTuples n = map readIntTuple <$> replicateM (fromIntegral n) BS.getLine
getIntTuples = map readIntTuple . BS.lines <$> BS.getContents
main=do
    getLine
    a <- getIntList
    let cnt = runST $ do
            --vec <- V.thaw $ V.fromList [1..m]
            --vec <- M.new m
            vec <- V.thaw $ V.replicate m 0
            forM_ a $ \ai ->
                forM_ (primeFactor ai) $ \j ->
                    M.modify vec (+1) j
            V.freeze vec

    putStrLn$if (V.and $V.map (<=1) cnt)
        then "pairwise coprime"
        else if (foldl1 gcd a == 1)
            then  "setwise coprime"
            else  "not coprime"
    --print $ V.take 20 cnt

m = 10^6+1

table :: Array Int Int
table = runSTArray $ do
    arr <- newArray (2,m) 0
    forM_ [2..m] $ \i -> writeArray arr i i
    forM_ (takeWhile (\i -> i*i < m) [2..]) $ \i -> do
        arri <- readArray arr i
        when (arri >= i)$
            forM_ (takeWhile (\j -> i*j < m) [i..]) $ \j -> do
                v <- readArray arr (i*j)
                when (v == i*j) $ writeArray arr (i*j) i
    return arr

primeFactor :: Int -> [Int]
primeFactor 1 = []
primeFactor n = if (null prev || head prev /= p) then p:prev else prev
    where p = table ! n
          prev = primeFactor (n `div` p)


{-# LANGUAGE BangPatterns #-}
import           Control.Exception           (assert)
import           Control.Monad
import           Control.Monad.Primitive
import qualified Control.Monad.ST            as ST
import qualified Data.Array.IO               as IO
import qualified Data.Array.ST               as ST
import qualified Data.Array.Unboxed          as A
import           Data.Bits
import qualified Data.ByteString.Char8       as BS
import           Data.Char
import           Data.Foldable
import           Data.List
import qualified Data.Map.Strict             as Map
import           Data.Maybe
import qualified Data.Sequence               as Seq
import qualified Data.Set                    as Set
import qualified Data.Vector                 as VB
import qualified Data.Vector.Mutable         as VBM
import qualified Data.Vector.Unboxed         as V
import qualified Data.Vector.Unboxed.Mutable as VM
import           Debug.Trace

readInt = fst . fromJust . BS.readInt
readIntList = map readInt . BS.words
getInt = readInt <$> BS.getLine
getIntList = readIntList <$> BS.getLine
getIntVec n = V.unfoldrN n (BS.readInt . BS.dropWhile isSpace) <$> BS.getLine

readInteger = fst . fromJust . BS.readInteger
readIntegerList = map readInteger . BS.words
getInteger = readInteger <$> BS.getLine
getIntegerList = readIntegerList <$> BS.getLine

inf :: Int
inf = 10^18

main = do
  n <- getInt
  as <- getIntVec n

  d1 <- VM.new (10^6+1)
  VM.set d1 (0::Int)
  d2 <- VM.new (10^6+1)
  VM.set d2 (0::Int)

  let sieve :: Int -> IO ()
      sieve i | i*i > 10^6 = return ()
              | otherwise = do
                  x <- VM.read d1 i
                  when (x == 0) $
                    forM_ [2..(10^6 `div` i)] $ \j -> do
                    let k = i * j
                    y <- VM.read d1 k
                    when (y == 0) $ VM.write d1 k i
                  sieve (i+1)

  sieve 2

  let pfactr :: Int -> Set.Set Int -> IO [Int]
      pfactr x s = do y <- VM.read d1 x
                      if y == 0
                        then return $ Set.toList (Set.insert x s)
                        else pfactr (x `div` y) (Set.insert y s)

      loop :: [Int] -> Int -> IO Int
      loop [] res = return res
      loop (f:fs) res = do
        t <- VM.read d2 f
        VM.write d2 f (t+1)
        let res' = max res (t+1)
        loop fs res'

      solve :: Int -> Int -> IO Int
      solve i res | i >= n = return res
                  | otherwise = do
                      let a = as V.! i
                      fs <- pfactr a Set.empty
                      res' <- loop fs res
                      solve (i+1) res'

  x <- solve 0 0
  let ans | x == 1 = "pairwise coprime"
          | x < n  = "setwise coprime"
          | otherwise = "not coprime"

  putStrLn ans


{-# LANGUAGE MultiWayIf #-}

module Main where

import Control.Monad
import Control.Monad.Extra
import qualified Data.Array as A
import qualified Data.Array.IO as AIO
import qualified Data.Array.Unboxed as AU
--import qualified Data.Heap                     as H

import Data.Bits
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BSC8
import Data.Char
import qualified Data.Graph.Inductive.Graph as G
import qualified Data.Graph.Inductive.PatriciaTree as G
import Data.Int
import Data.List
import qualified Data.Map.Strict as M
import Data.Maybe
import Data.Monoid
import Data.Ord
import qualified Data.Sequence as SQ
import qualified Data.Set as S
import qualified Data.Vector as V
import Data.Vector.Algorithms.Search
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import Debug.Trace
import Prelude

main =
  do
    --aN       <- getI
    --[aA, aB] <- getIL
    --aS       <- getLine

    aN <- getI
    aA <- getIL

    let (aaa, _) = foldl (\acc@(a, b) x -> ((gcd b x), b * x)) (1, head aA) $tail aA
    let bbb = foldl1 (\acc x -> gcd acc x) aA
    if aaa == 1
      then putStrLn "pairwise coprime"
      else
        if bbb == 1
          then putStrLn "setwise coprime"
          else putStrLn "not coprime"
    return ()

{-
hMaxPoint :: Int
hMaxPoint = 101
hMaximum :: H.Heap Int -> Int
hMaximum h = hMaxPoint - (H.minimum h)
hInsertMax :: Int -> H.Heap Int -> H.Heap Int
hInsertMax x = H.insert (hMaxPoint - x)
hDeleteMax :: H.Heap Int -> H.Heap Int
hDeleteMax = H.deleteMin
-}
{-}
aroundSquare y x h w =
  [ aYX
    | aYX@(aY, aX) <- [(y - 1, x), (y, x - 1), (y + 1, x), (y, x + 1), (y, x)],
      aY >= 0,
      aY <= (h - 1),
      aX >= 0,
      aX <= (w - 1)
  ]
-}

aroundSquare y x h w =
  [ aYX
    | aYX@(aY, aX) <- [(y + a, x + b) | a <- [-1 .. 1], b <- [-1 .. 1], abs (a) + abs (b) == 1],
      aY >= 1,
      aY <= (h),
      aX >= 1,
      aX <= (w),
      (aY /= y) || (aX /= x)
  ]

warpAroundSquare y x h w =
  [ aYX
    | aYX@(aY, aX) <- [(y + a, x + b) | a <- [-2 .. 2], b <- [-2 .. 2], abs (a) + abs (b) > 1],
      aY >= 1,
      aY <= (h),
      aX >= 1,
      aX <= (w),
      (aY /= y) || (aX /= x)
  ]

splitReadBSC8 :: BSC8.ByteString -> [Int]
splitReadBSC8 bs =
  let (bs1, newBs) = BSC8.splitAt 1 bs
   in if newBs == BSC8.empty
        then [test $ BSC8.readInt bs1]
        else (test $ BSC8.readInt bs1) : (splitReadBSC8 newBs)
  where
    test (Just (i, _)) = i

read2DimChar :: VM.IOVector (VUM.IOVector Char) -> Int -> Int -> IO Char
read2DimChar vec y x = do
  vecY <- VM.read vec y
  VUM.read vecY x

write2DimChar :: VM.IOVector (VUM.IOVector Char) -> Int -> Int -> Char -> IO ()
write2DimChar vec y x t = do
  vecY <- VM.read vec y
  VUM.write vecY x t

readTwoDimVec :: VM.IOVector (VUM.IOVector Int) -> Int -> Int -> IO Int
readTwoDimVec vec y x = do
  vecY <- VM.read vec y
  VUM.read vecY x

writeTwoDimVec :: VM.IOVector (VUM.IOVector Int) -> Int -> Int -> Int -> IO ()
writeTwoDimVec vec y x t = do
  vecY <- VM.read vec y
  VUM.write vecY x t

getVUI :: IO (VU.Vector Int)
getVUI = VU.unfoldr (BSC8.readInt . BSC8.dropWhile isSpace) <$> BSC8.getLine

getRepVUI :: Int -> IO (VU.Vector Int)
getRepVUI n =
  VU.unfoldr (BSC8.readInt . BSC8.dropWhile isSpace)
    . BSC8.unlines
    <$> replicateM n BSC8.getLine

getVS :: IO (V.Vector Char)
getVS = V.fromList <$> getLine

getVUC :: IO (VU.Vector Char)
getVUC = VU.fromList <$> getLine

readI :: BSC8.ByteString -> Int
readI = fst . fromJust . BSC8.readInt

readIL :: BSC8.ByteString -> [Int]
readIL = map readI . BSC8.words

readIT2 :: BSC8.ByteString -> (Int, Int)
readIT2 bs =
  let words = BSC8.words bs in (readI $ head words, readI $ last words)

getI :: IO Int
getI = readI <$> BSC8.getLine

getIL :: IO [Int]
getIL = readIL <$> BSC8.getLine

getIT2 :: IO (Int, Int)
getIT2 = readIT2 <$> BSC8.getLine

getIT2Order :: IO (Int, Int)
getIT2Order =
  getIL
    >>= \x@[xz, xo] -> if xz > xo then return (xo, xz) else return (xz, xo)

getNIS :: Int -> IO [(Int, BSC8.ByteString)]
getNIS 0 = return []
getNIS n = do
  [aFst, aSnd] <- BSC8.words <$> BSC8.getLine
  next <- getNIS (n - 1)
  return ((readI aFst, aSnd) : next)

il2Words :: [Int] -> String
il2Words = unwords . map show

il2Lines :: [Int] -> String
il2Lines = unlines . map show

p :: Int -> Int
p x = x - 1

--modNum = 10 ^ 9 + 7
--modulus = 1000000007
modulus = 1000000007

newtype MInt = M Int

instance Num MInt where
  (M a) + (M b) = M $ mod (a + b) modulus

  (M a) - (M b) = M $ mod (a - b) modulus

  (M a) * (M b) = M $ mod (a * b) modulus

  fromInteger a = M $ mod (fromInteger a) modulus

  abs (M a) = undefined

  signum (M a) = undefined

instance Show MInt where
  show (M a) = show (mod a modulus)

int2MInt :: Int -> MInt
int2MInt a = M (mod a modulus)

mInt2Int :: MInt -> Int
mInt2Int (M a) = a

{-
factsMod :: V.Vector MInt
factsMod = V.scanl (\acc x -> M x * acc) 1 $ V.generate 2000000 (+ 1)

factMod :: Int -> MInt
factMod = (factsMod V.!)
-}

factMod :: Int -> MInt
factMod n
  | n == 0 = 1
  | n == 1 = 1
  | otherwise = M n * (factMod (n - 1))

factDivMod :: Int -> Int -> MInt
factDivMod n k
  | n == k = M 1
  | otherwise = M n * (factDivMod (n - 1) k)

powMod :: MInt -> MInt -> MInt
powMod n mK@(M k)
  | k == 0 = M 1
  | k == 1 = n
  | mod k 2 == 0 = powMod (n ^ 2) (M (div k 2))
  | otherwise = n * powMod (n ^ 2) (M (div k 2))

invMod :: MInt -> MInt
invMod (M 0) = error "inverse of 0"
invMod x = powMod x (M (modulus - 2))

{-
combiMod :: Int -> Int -> MInt
combiMod n k
  | n < 0 || k < 0 || k > n = 0
  | otherwise = factMod n * invMod (factMod (n - k)) * invMod (factMod k)
-}
combiMod :: Int -> Int -> MInt
combiMod n k
  | n < 0 || k < 0 || k > n = 0
  | k > n - k = factDivMod n k * invMod (factMod (n - k))
  | otherwise = factDivMod n (n - k) * invMod (factMod k)

combi :: Int -> Int -> Int
combi n k
  | n < 0 || k < 0 || k > n = 0
  | k == n = 1
  | otherwise = div (div (fact n) (fact (n - k))) (fact k)

{-w
primes :: Integral a => [a]
primes = map fromIntegral $ [2, 3] ++ primes'
 where
  primes' = [5] ++ f 1 7 primes'
  f m s (p : ps) = [ n | n <- ns, gcd m n == 1 ] ++ f (m * p) (p * p) ps
    where ns = [ x + y | x <- [s, s + 6 .. p * p - 2], y <- [0, 4] ]

prime n = primes !! n
primes = sieve [2 ..]
sieve (p : xs) = p : sieve [ x | x <- xs, x `mod` p /= 0 ]
-}
fact :: Int -> Int
fact 0 = 1
fact n | n > 0 = n * fact (n - 1)

knappsackWDP :: Int -> [(Int, Int)] -> VU.Vector Int
knappsackWDP maxW [] = VU.replicate (maxW + 1) 0
knappsackWDP maxW ((w, v) : xs) =
  let tailDP = knappsackWDP maxW xs
   in VU.generate (maxW + 1) $ \i ->
        if w <= i
          then max (tailDP VU.! i) (tailDP VU.! (i - w) + v)
          else tailDP VU.! i

knappsackVDP :: Int -> Int -> Int -> [(Int, Int)] -> VU.Vector Int
knappsackVDP maxW maxV n [] = VU.cons 0 $ VU.replicate (n * maxV) maxW
knappsackVDP maxW maxV n ((w, v) : xs) =
  let tailDP = knappsackVDP maxW maxV n xs
   in VU.generate (n * maxV + 1) $ \i ->
        if v <= i
          then min (tailDP VU.! i) (tailDP VU.! (i - v) + w)
          else tailDP VU.! i

knappsackMinVol ::
  AIO.IOArray (Int, Int) Int ->
  VU.Vector Int ->
  VU.Vector Int ->
  Int ->
  Int ->
  IO Int
knappsackMinVol dp volumeVec valueVec dpSize maxVolume = do
  mapM_
    ( \i ->
        mapM_
          ( \v -> do
              let volume = volumeVec VU.! i
                  value = valueVec VU.! i
              newdp <-
                if (v + value) > dpSize
                  then AIO.readArray dp (i, v)
                  else do
                    dpIVm <- AIO.readArray dp (i, v + value)
                    dpIV <- AIO.readArray dp (i, v)
                    return (min (dpIVm - volume) dpIV)
              AIO.writeArray dp (i + 1, v) newdp
          )
          (reverse [0 .. dpSize])
    )
    [0 .. VU.length valueVec - 1]
  foldM
    ( \acc x -> do
        num <- AIO.readArray dp (VU.length volumeVec, x)
        return $ if num <= maxVolume then x else acc
    )
    0
    [0 .. dpSize]

lcsTable :: BS.ByteString -> BS.ByteString -> V.Vector (VU.Vector Int)
lcsTable xs ys = V.scanl step (VU.replicate (m + 1) 0) xs'
  where
    n = BS.length xs
    m = BS.length ys
    xs' = V.generate n $ BSC8.index xs :: V.Vector Char
    ys' = VU.generate m $ BSC8.index ys :: VU.Vector Char
    step :: VU.Vector Int -> Char -> VU.Vector Int
    step v x = VU.scanl innerStep 0 (VU.zip3 v (VU.tail v) ys')
      where
        innerStep :: Int -> (Int, Int, Char) -> Int
        innerStep a (b, c, y)
          | x == y = 1 + b
          | otherwise = max a c

{-
main = do
xs <- BS.getLine
ys <- BS.getLine
print $ VU.last $ V.last $ lcsTable xs ys
-}

myFilter :: (a -> Bool) -> [a] -> ([a], [a])
myFilter _pred [] = ([], [])
myFilter pred (x : xs)
  | pred x = let (l, r) = myFilter pred xs in (x : l, r)
  | otherwise = let (l, r) = myFilter pred xs in (l, x : r)

--UnionFindデータ構造

type UF_PARENT = VUM.IOVector Int

type UF_RANK = VUM.IOVector Int

type UF = (UF_PARENT, UF_RANK)

uf_makeSet :: Int -> IO UF
uf_makeSet n = do
  parent <- VU.thaw $ VU.generate n id
  rank <- VUM.replicate n 0
  return (parent, rank)

uf_union :: UF -> Int -> Int -> IO ()
uf_union unionFind@(parents, ranks) x y = do
  xRoot <- uf_find unionFind x
  yRoot <- uf_find unionFind y

  xRootRank <- VUM.read ranks xRoot
  yRootRank <- VUM.read ranks yRoot
  if
      | xRootRank > yRootRank -> VUM.write parents yRoot xRoot
      | xRootRank < yRootRank -> VUM.write parents xRoot yRoot
      | xRoot /= yRoot -> do
        VUM.write parents yRoot xRoot
        VUM.write ranks xRoot (xRootRank + 1)
      | otherwise -> return ()

uf_find :: UF -> Int -> IO Int
uf_find unionFind@(parents, ranks) x = do
  xParent <- VUM.read parents x
  if xParent == x
    then return x
    else do
      xRootParent <- uf_find unionFind xParent
      VUM.write parents x xRootParent
      return xRootParent

--UnDirectedGraph(無向グラフ)データ構造

type UDG = M.Map Int [Int]

list2UDG :: [(Int, Int)] -> M.Map Int [Int]
list2UDG =
  foldl
    ( \acc x ->
        let lr = M.insertWith (++) (fst x) [snd x] acc
         in M.insertWith (++) (snd x) [fst x] lr
    )
    M.empty


{-# LANGUAGE BangPatterns #-}
import           Control.Exception           (assert)
import           Control.Monad
import           Control.Monad.Primitive
import qualified Control.Monad.ST            as ST
import qualified Data.Array.IO               as IO
import qualified Data.Array.ST               as ST
import qualified Data.Array.Unboxed          as A
import           Data.Bits
import qualified Data.ByteString.Char8       as BS
import           Data.Char
import           Data.Foldable
import           Data.List
import qualified Data.Map.Strict             as Map
import           Data.Maybe
import qualified Data.Sequence               as Seq
import qualified Data.Set                    as Set
import qualified Data.Vector                 as VB
import qualified Data.Vector.Mutable         as VBM
import qualified Data.Vector.Unboxed         as V
import qualified Data.Vector.Unboxed.Mutable as VM
import           Debug.Trace

readInt = fst . fromJust . BS.readInt
readIntList = map readInt . BS.words
getInt = readInt <$> BS.getLine
getIntList = readIntList <$> BS.getLine
getIntVec n = V.unfoldrN n (BS.readInt . BS.dropWhile isSpace) <$> BS.getLine

readInteger = fst . fromJust . BS.readInteger
readIntegerList = map readInteger . BS.words
getInteger = readInteger <$> BS.getLine
getIntegerList = readIntegerList <$> BS.getLine

inf :: Int
inf = 10^18

m = 63

ps = V.fromList $ take m  [2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
                           31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
                           73, 79, 83, 89, 97, 101, 103, 107, 109,
                           113, 127, 131, 137, 139, 149, 151, 157,
                           163, 167, 173, 179, 181, 191, 193, 197,
                           199, 211, 223, 227, 229, 233, 239, 241,
                           251, 257, 263, 269, 271, 277, 281, 283,
                           293, 307, 311, 313, 317, 331, 337, 347,
                           349, 353, 359, 367, 373, 379, 383, 389,
                           397, 401, 409, 419, 421, 431, 433, 439,
                           443, 449, 457, 461, 463, 467, 479, 487,
                           491, 499, 503, 509, 521, 523, 541, 547,
                           557, 563, 569, 571, 577, 587, 593, 599,
                           601, 607, 613, 617, 619, 631, 641, 643,
                           647, 653, 659, 661, 673, 677, 683, 691,
                           701, 709, 719, 727, 733, 739, 743, 751,
                           757, 761, 769, 773, 787, 797, 809, 811,
                           821, 823, 827, 829, 839, 853, 857, 859,
                           863, 877, 881, 883, 887, 907, 911, 919,
                           929, 937, 941, 947, 953, 967, 971, 977,
                           983, 991, 997]

ps2 = V.fromList $ take m $ drop m ([2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
                                    31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
                                    73, 79, 83, 89, 97, 101, 103, 107, 109,
                                    113, 127, 131, 137, 139, 149, 151, 157,
                                    163, 167, 173, 179, 181, 191, 193, 197,
                                    199, 211, 223, 227, 229, 233, 239, 241,
                                    251, 257, 263, 269, 271, 277, 281, 283,
                                    293, 307, 311, 313, 317, 331, 337, 347,
                                    349, 353, 359, 367, 373, 379, 383, 389,
                                    397, 401, 409, 419, 421, 431, 433, 439,
                                    443, 449, 457, 461, 463, 467, 479, 487,
                                    491, 499, 503, 509, 521, 523, 541, 547,
                                    557, 563, 569, 571, 577, 587, 593, 599,
                                    601, 607, 613, 617, 619, 631, 641, 643,
                                    647, 653, 659, 661, 673, 677, 683, 691,
                                    701, 709, 719, 727, 733, 739, 743, 751,
                                    757, 761, 769, 773, 787, 797, 809, 811,
                                    821, 823, 827, 829, 839, 853, 857, 859,
                                    863, 877, 881, 883, 887, 907, 911, 919,
                                    929, 937, 941, 947, 953, 967, 971, 977,
                                    983, 991, 997] :: [Int])

num2pbits n i b | i >= m = b
                | otherwise = let x = (1::Int) `shiftL` i
                                  p = ps V.! i
                                  b' = if n `mod` p == 0
                                       then b + x
                                       else b
                              in if p < n
                                 then num2pbits n (i+1) b'
                                 else b'

num2pbit2 n i b | i >= m = b
                | otherwise = let x = (1::Int) `shiftL` i
                                  p = ps2 V.! i
                                  b' = if n `mod` p == 0
                                       then b + x
                                       else b
                              in if p < n
                                 then num2pbits n (i+1) b'
                                 else b'

main = do
  n <- getInt
  as <- getIntVec n

  let as' = V.map (\x -> num2pbits x 0 0) as
      as2' = V.map (\x -> num2pbit2 x 0 0) as
      band = V.foldr1 (.&.) as' -- band == 0 => setwise coprime
      band2 = V.foldr1 (.&.) as2' -- band == 0 => setwise coprime

      checkPairwise i d | i >= n = True
                        | otherwise = let x = as' V.! i
                                      in if d .&. x /= 0
                                         then False
                                         else checkPairwise (i+1) (d .|. x)

      checkPairwis2 i d | i >= n = True
                        | otherwise = let x = as2' V.! i
                                      in if d .&. x /= 0
                                         then False
                                         else checkPairwis2 (i+1) (d .|. x)

      ans | checkPairwise 0 0 && checkPairwis2 0 0 = "pairwise coprime"
          | band == 0 && band2 == 0         = "setwise coprime"
          | otherwise         = "not coprime"

  putStrLn ans