{-# LANGUAGE BangPatterns #-} import Control.Monad.Fix import Control.Monad.ST import Data.Bool import qualified GHC.Integer.GMP.Internals as GMP import qualified Data.Vector.Unboxed as VU import qualified Data.Vector.Unboxed.Mutable as VUM main :: IO () main = do [a, b, n] <- map read . words <$> getLine print $ tetration a b n tetration :: Int -> Int -> Int -> Int tetration a b m | m == 1 = 0 | a == 0 = bool 0 1 (even b) | b == 0 = 1 | b == 1 = a `mod` m | b == 2 = powModInt (a `mod` m) a m | otherwise = powModInt (a `mod` m) (prev + phi) m where !phi = eulerPhi m prev = tetration a (b - 1) phi powModInt :: Int -> Int -> Int -> Int powModInt a b c = fromInteger $ GMP.powModInteger (fromIntegral a) (fromIntegral b) (fromIntegral c) {-# INLINE powModInt #-} eulerPhi :: Int -> Int eulerPhi n = runST $ do xs <- VU.unsafeThaw $ VU.fromList [n, n, 2] ys <- loopFor xs p <- VUM.unsafeRead ys 0 q <- VUM.unsafeRead ys 1 if q > 1 then return (p - p `div` q) else return p where loopFor :: VUM.STVector s Int -> ST s (VUM.STVector s Int) loopFor xx = do idx <- VUM.unsafeRead xx 2 if idx * idx > n then return xx else do xret <- VUM.unsafeRead xx 0 xn <- VUM.unsafeRead xx 1 if xn `mod` idx /= 0 then do VUM.unsafeWrite xx 2 (idx + 1) loopFor xx else do VUM.unsafeWrite xx 0 (xret - xret `div` idx) whileXS <- loopWhile xx VUM.unsafeWrite whileXS 2 (idx + 1) loopFor whileXS where loopWhile :: VUM.STVector s Int -> ST s (VUM.STVector s Int) loopWhile ks = do whileN <- VUM.unsafeRead ks 1 whileI <- VUM.unsafeRead ks 2 if whileN `mod` whileI /= 0 then return ks else do VUM.unsafeWrite ks 1 (whileN `div` whileI) loopWhile ks