use std::io::{BufWriter, Write, read_to_string, stdin, stdout};

const MOD: usize = 1_000_000_007;

/*
    IMPLEMENTATION MONOID-FN
*/

pub trait MonoidFn<T> {
    fn call(&self, a: &T, b: &T) -> T;
    fn identity(&self) -> T;
}

/*
    IMPLEMENTATION SEG-TREE ON MONOID-FN<T>
*/
struct SegTree<T: Clone, F>
where
    F: MonoidFn<T>,
{
    pub op: F,
    size: usize,
    tree: Vec<T>,
}

impl<T: Clone, F> SegTree<T, F>
where
    F: MonoidFn<T>,
{
    fn new(arr: &Vec<T>, op: F) -> Self {
        let size = arr.len();

        let mut tree = vec![op.identity(); size * 4];

        let mut stack = vec![]; // (inst, index, [lo, hi))

        stack.push((1, 0, 0, size)); // 빼면서 업데이트
        stack.push((0, 0, 0, size)); // 넣기

        while !stack.is_empty() {
            let (inst, index, lo, hi) = stack.pop().unwrap();
            if inst == 0 {
                if hi - lo == 1 {
                    tree[index] = arr[lo].clone();
                } else {
                    let mid = (lo + hi) / 2;
                    let left_index = index * 2 + 1;
                    let right_index = index * 2 + 2;
                    stack.push((1, left_index, lo, mid));
                    stack.push((0, left_index, lo, mid));

                    stack.push((1, right_index, mid, hi));
                    stack.push((0, right_index, mid, hi));
                }
            } else {
                if hi - lo == 1 {
                    continue;
                } else {
                    let left_index = index * 2 + 1;
                    let right_index = index * 2 + 2;
                    tree[index] = op.call(&tree[left_index], &tree[right_index]);
                }
            }
        }

        SegTree { op, size, tree }
    }

    fn query(&self, idx: usize, lo: usize, hi: usize, qlo: usize, qhi: usize) -> T {
        if qlo >= hi || qhi <= lo {
            self.op.identity()
        } else if qlo <= lo && hi <= qhi {
            self.tree[idx].clone()
        } else {
            let mid = (lo + hi) / 2;
            let left_value = self.query(idx * 2 + 1, lo, mid, qlo, qhi);
            let right_value = self.query(idx * 2 + 2, mid, hi, qlo, qhi);
            self.op.call(&left_value, &right_value)
        }
    }

    fn modify(&mut self, idx: usize, lo: usize, hi: usize, pos: usize, val: &T) {
        if pos < lo || pos >= hi {
            return;
        }
        if hi - lo == 1 {
            self.tree[idx] = val.clone();
            return;
        }
        let mid = (lo + hi) / 2;
        self.modify(idx * 2 + 1, lo, mid, pos, val);
        self.modify(idx * 2 + 2, mid, hi, pos, val);
        self.tree[idx] = self
            .op
            .call(&self.tree[idx * 2 + 1], &self.tree[idx * 2 + 2]);
    }
}

struct MulMod;

impl MonoidFn<usize> for MulMod {
    fn call(&self, a: &usize, b: &usize) -> usize {
        (a * b) % MOD
    }
    fn identity(&self) -> usize {
        1
    }
}

fn main() {
    let temp = read_to_string(stdin()).unwrap();
    let mut iter = temp
        .split_ascii_whitespace()
        .map(|x| x.parse::<usize>().unwrap());

    let (n, m, k) = (
        iter.next().unwrap(),
        iter.next().unwrap(),
        iter.next().unwrap(),
    );

    let op = MulMod;

    let arr = (0..n).map(|_| iter.next().unwrap()).collect::<Vec<_>>();

    let mut out = BufWriter::new(stdout());

    let mut segtr = SegTree::new(&arr, op);
    for _ in 0..m + k {
        let (a, b, c) = (
            iter.next().unwrap(),
            iter.next().unwrap() - 1,
            iter.next().unwrap(),
        );

        if a == 2 {
            let res = segtr.query(0, 0, n, b, c);
            writeln!(out, "{}", res).unwrap();
        } else {
            segtr.modify(0, 0, n, b, &c);
        }
    }
}
