#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const LL MOD = 1e9 + 7;
LL modpow(LL a, LL n) {
  if (n < 0) {
    a = modpow(a, MOD - 2);
    n = -n;
  }
  LL res = 1;
  for (a %= MOD; n > 0; n >>= 1) {
    if (n & 1) res = (res * a) % MOD;
    a = (a * a) % MOD;
  }
  return res;
}
const int N = 4e5, M = 301, P = 62;
LL prime_mask[M];
class SegmentTree {
  vector<LL> tree, lazy;
  vector<LL> mtree, mlazy;
  int sz;
  void split(int node, int x, int y) {
    int z = (x + y) / 2;
    if (lazy[node] != 1) {
      tree[2 * node] = (tree[2 * node] * modpow(lazy[node], z - x)) % MOD;
      lazy[2 * node] = (lazy[2 * node] * lazy[node]) % MOD;
      tree[2 * node + 1] =
          (tree[2 * node + 1] * modpow(lazy[node], y - z)) % MOD;
      lazy[2 * node + 1] = (lazy[2 * node + 1] * lazy[node]) % MOD;
      lazy[node] = 1;
    }
    mtree[2 * node] |= mlazy[node];
    mlazy[2 * node] |= mlazy[node];
    mtree[2 * node + 1] |= mlazy[node];
    mlazy[2 * node + 1] |= mlazy[node];
  }
  void merge(int node, int x, int y) {
    tree[node] = (tree[2 * node] * tree[2 * node + 1]) % MOD;
    mtree[node] = mtree[2 * node] | mtree[2 * node + 1];
  }

 public:
  SegmentTree(int n) {
    for (sz = 1; sz < n; sz <<= 1)
      ;
    tree.resize(2 * sz, 1);
    lazy.resize(2 * sz, 1);
    mtree.resize(2 * sz, 0);
    mlazy.resize(2 * sz, 0);
  }
  void update(int l, int r, int d, int node = 1, int x = 0, int y = -1) {
    if (y == -1) y = sz;
    if (l >= y || r <= x) return;
    if (l <= x && r >= y) {
      tree[node] = (tree[node] * modpow(d, y - x)) % MOD;
      lazy[node] = (lazy[node] * d) % MOD;
      mtree[node] |= prime_mask[d];
      mlazy[node] |= prime_mask[d];
      return;
    }
    split(node, x, y);
    update(l, r, d, 2 * node, x, (x + y) / 2);
    update(l, r, d, 2 * node + 1, (x + y) / 2, y);
    merge(node, x, y);
  }
  pair<LL, LL> query(int l, int r, int node = 1, int x = 0, int y = -1) {
    if (y == -1) y = sz;
    if (l >= y || r <= x) return {1, 0};
    if (l <= x && r >= y) {
      return {tree[node], mtree[node]};
    }
    split(node, x, y);
    auto lres = query(l, r, 2 * node, x, (x + y) / 2);
    auto rres = query(l, r, 2 * node + 1, (x + y) / 2, y);
    merge(node, x, y);
    return {(lres.first * rres.first) % MOD, lres.second | rres.second};
  }
};
LL mult[P];
void prec() {
  map<int, int> pid;
  vector<bool> isprime(M, true);
  for (int i = 2; i < M; i++) {
    if (isprime[i]) {
      int idx = pid.size();
      pid[i] = idx;
      mult[idx] = ((i - 1) * modpow(i, -1)) % MOD;
      for (int j = 2 * i; j < M; j += i) isprime[j] = false;
    }
    for (int val = i, p = 2; val > 1 && p <= val; p++) {
      while (val % p == 0) val /= p, prime_mask[i] |= 1ll << pid[p];
    }
  }
}
LL get_phi(LL mask) {
  LL res = 1;
  for (int i = 0; i < 62; i++) {
    if ((mask >> i) & 1) {
      res = (res * mult[i]) % MOD;
    }
  }
  return res;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  prec();
  int n, q;
  cin >> n >> q;
  SegmentTree st(n);
  for (int i = 0; i < n; i++) {
    int a;
    cin >> a;
    st.update(i, i + 1, a);
  }
  while (q--) {
    string ty;
    int l, r;
    cin >> ty >> l >> r;
    if (ty[0] == 'M') {
      int a;
      cin >> a;
      st.update(l - 1, r, a);
    } else {
      auto res = st.query(l - 1, r);
      LL ans = (res.first * get_phi(res.second)) % MOD;
      cout << ans << '\n';
    }
  }
  return 0;
}
