Minimum Multiple
Difficulty: Hard

Calculi is Lambda's older brother. Lambda is mischievous and always annoys Calculi by asking silly questions. This time around, Lambda would like to surprise Calculi by asking a challenging and interesting question.  To that end, Lambda gives Calculi an array of $N$ integers, $A = \{a_0, a_1,\ldots, a_{N-1}\}$, followed by $K$ queries. Each query is of two types:


- $Q\ l\ r$: Find the minimum positive integer, $M$, such that each element in subarray $arr[l\ldots r]\ (\{a_l, a_{l+1},\ldots, a_r\})$ divides $M$.
- $U\ idx\ val$: Multiply the value at $idx$ by $val$. That is $a_{idx}' = a_{idx} \times val$, where $a'_{idx}$ is the updated value.

Your task is to help Calculi tackle this challenge. For each query of type $''Q\ l\ r''$, find the value of $M$. As this value can be very large, print the $M$ modulo $(10^9+7)$, i.e., $M \% (10^9+7)$. For query of type $''U\ idx\ val''$, update the required element.


Input Format:
The first line contains an integer, $N$, which represents the length of array, $A$.  
In second line, there are $N$ space-separated integers, $a_0, a_1,\ldots, a_{N-1}$, representing the elements of $A$.  
In third line, there is another integer, $K$, which is the count of queries to follow.   
Then follows $K$ lines, each representing a query of one of the types described above.  

Output Format:
For each query of type `Q l r`, print the value of $M \% (10^9+7)$ on a new line.

Sample Input:
	5
	2 5 6 1 9
	7
	Q 0 4
	U 1 2
	Q 0 2
	Q 3 4
	Q 2 4
	U 3 8
	Q 2 3

Sample Output:
	90
	30
	9
	18
	24

Python 3 starter code:


Reference solution (Python):
    module Main where

    import Control.Applicative
    import Data.List
    import qualified Data.Map as Map
    import Control.Arrow ((&&&))

    p :: Int
    p = 10^(9::Int)+7

    primeFactors :: Map.Map Int [(Int, Int)]
    primeFactors =
      Map.fromList. zip [1..]. map (map (head &&& length). group. factorize 2) $ [1..100]
      where
        factorize v n
          | v*v > n        = if n == 1 then [] else [n]
          | n `rem` v == 0 = v: factorize v (n`div`v)
          | otherwise      = factorize (succ v) n

    power :: Int -> Int -> Int
    power _ 0     = 1
    power a b
      | even b    = ret
      | otherwise = (a*ret) `rem` p
        where tmp = power a (b`div`2)
              ret = (tmp*tmp)`rem`p

    factorToValue :: [(Int, Int)] -> Int
    factorToValue [] = 1
    factorToValue ((a,b):xs) = let f = power a b in (f * factorToValue xs)`rem`p

    data SegTree = Node {
                      factor                :: Map.Map Int Int
                    , startIdx, endIdx      :: Int
                    , leftChild, rightChild :: SegTree
                   }
                 | Leaf {
                      factor                :: Map.Map Int Int
                    , startIdx, endIdx      :: Int
                   }


    isLeaf, isNode :: SegTree -> Bool
    isLeaf (Leaf {}) = True
    isLeaf _         = False
    isNode           = not. isLeaf

    initSegTree :: Int -> SegTree
    initSegTree n = initSegTree' 0 (n-1)
      where
        initSegTree' l r
          | l == r    = Leaf {factor = Map.empty, startIdx = l, endIdx = l}
          | otherwise =
            let mid = (l+r)`div`2
            in  Node { factor = Map.empty, startIdx = l, endIdx = r
                     , leftChild  = initSegTree' l mid
                     , rightChild = initSegTree' (succ mid) r
                     }

    getFactors :: Int -> SegTree -> Map.Map Int Int
    getFactors _   (Leaf {factor = f}) = f
    getFactors idx nd
      | idx <= endIdx (leftChild nd)   = getFactors idx (leftChild  nd)
      | otherwise                      = getFactors idx (rightChild nd)

    mergePowers :: [(Int, Int)] -> [(Int, Int)] -> [(Int, Int)]
    mergePowers [] ys = ys
    mergePowers xs [] = xs
    mergePowers xxs@((a1,b1):xs) yys@((a2,b2):ys)
      | a1 == a2  = (a1, b1+b2): mergePowers xs  ys
      | a1 < a2   = (a1, b1)   : mergePowers xs  yys
      | otherwise = (a2, b2)   : mergePowers xxs ys


    bestPowers :: [(Int, Int)] -> [(Int, Int)] -> [(Int, Int)]
    bestPowers [] ys = ys
    bestPowers xs [] = xs
    bestPowers xxs@((a1,b1):xs) yys@((a2,b2):ys)
      | a1 == a2  = (a1, max b1 b2): bestPowers xs  ys
      | a1 < a2   = (a1, b1)       : bestPowers xs  yys
      | otherwise = (a2, b2)       : bestPowers xxs ys

    main :: IO ()
    main = do
      n       <- read <$> getLine
      arr     <- map read. words <$> getLine
      k       <- (read::String->Int) <$> getLine
      queries <- map (\x -> (\[[p'], q, r] -> (p', read q, read r)). words $ x). lines <$> getContents
      mapM_ print (solve n arr queries)

    solve ::  Int -> [Int] -> [(Char, Int, Int)] -> [Int]
    solve n arr queries = processQueries queries origTree
      where
        origTree = foldr (\(idx, val) root -> updateTree idx (primeFactors Map.! val) root)
                         (initSegTree n)
                         (zip [0..] arr)

    processQueries :: [(Char, Int, Int)] -> SegTree -> [Int]
    processQueries [] _ = []
    processQueries (('Q', l, r):q) root =
      let ans = factorToValue $ rangeQuery (l, r) root
      in  ans : processQueries q root
    processQueries (('U', idx, val):q) root =
      let origFactor = Map.toList (getFactors idx root)
          newFactor  = mergePowers origFactor (primeFactors Map.! val)
          newRoot    = updateTree idx newFactor root
      in  processQueries q newRoot

    rangeQuery :: (Int, Int) -> SegTree -> [(Int, Int)]
    rangeQuery range@(l, r) nd
      | r < startIdx nd = []
      | l > endIdx   nd = []
      | l <= startIdx nd  && endIdx nd <= r = Map.toList (factor nd)
      | otherwise = bestPowers
                      (rangeQuery range (leftChild nd))
                      (rangeQuery range (rightChild nd))

    updateTree :: Int -> [(Int, Int)] -> SegTree -> SegTree
    updateTree idx factors node
      | startIdx node <= idx && idx <= endIdx node =
        case node of
          Leaf {} -> node {factor = updatedFactors}
          _       -> node {factor = updatedFactors, leftChild = lChild, rightChild = rChild}
      where
        lChild = updateTree idx factors (leftChild  node)
        rChild = updateTree idx factors (rightChild node)
        updatedFactors = foldr (\(base, p_new) fact -> updatePower base p_new fact) (factor node) factors
    updateTree _ _ node = node

    updatePower :: Int -> Int -> Map.Map Int Int -> Map.Map Int Int
    updatePower base p_new fact =
      let p_old = Map.findWithDefault 0 base fact
      in  if p_new > p_old then Map.insert base p_new fact
          else fact

    isPrime n = not. any (\x -> n `rem` x == 0) $ [2..(n-1)]