#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x) {
  x = 0;
  char ch = 0;
  bool sign = false;
  while (ch < '0' || '9' < ch) sign |= ch == '-', ch = getchar();
  while ('0' <= ch && ch <= '9')
    x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
  x = sign ? -x : x;
}
template <typename T>
inline void print(T x) {
  static char outp[64];
  if (!x) {
    putchar('0');
    return;
  }
  if (x < 0) putchar('-'), x = -x;
  int tot = 0;
  while (x) outp[tot++] = x % 10 + '0', x /= 10;
  while (tot) putchar(outp[--tot]);
}
const int MOD = 1e9 + 7;
const int MAXN = 4e5 + 10;
const int MAXT = (1 << 20) + 10;
bool is_p[305];
int ary[MAXN], fmul[305], Set[305];
vector<int> prime;
inline int qpow(int x, int y) {
  int ret = 1;
  while (y) {
    if (y & 1) ret = ret * 1ll * x % MOD;
    x = x * 1ll * x % MOD;
    y >>= 1;
  }
  return ret;
}
struct Segment_tree {
  struct Node {
    int l, r;
    int mul, val;
    bitset<64> factor, pd;
  } tree[MAXT];
  bitset<64> qry, prm;
  inline void solve(int x) {
    prm.reset();
    int sq = sqrt(x);
    for (register int i = 1; i <= (int)sq; ++i) {
      if (x % i == 0) {
        if (!is_p[i]) prm[Set[i]] = 1;
        if (!is_p[x / i]) prm[Set[x / i]] = 1;
      }
    }
  }
  inline void update(int root) {
    tree[root].val =
        tree[(root << 1)].val * 1ll * tree[(root << 1 | 1)].val % MOD;
    tree[root].factor |=
        tree[(root << 1)].factor | tree[(root << 1 | 1)].factor;
  }
  inline void pushdown(int root) {
    tree[(root << 1)].mul = tree[(root << 1)].mul * 1ll * tree[root].mul % MOD;
    tree[(root << 1 | 1)].mul =
        tree[(root << 1 | 1)].mul * 1ll * tree[root].mul % MOD;
    tree[(root << 1)].val =
        tree[(root << 1)].val * 1ll *
        qpow(tree[root].mul, tree[(root << 1)].r - tree[(root << 1)].l + 1) %
        MOD;
    tree[(root << 1 | 1)].val =
        tree[(root << 1 | 1)].val * 1ll *
        qpow(tree[root].mul,
             tree[(root << 1 | 1)].r - tree[(root << 1 | 1)].l + 1) %
        MOD;
    tree[(root << 1)].factor |= (tree[(root << 1)].pd |= tree[root].pd);
    tree[(root << 1 | 1)].factor |= (tree[(root << 1 | 1)].pd |= tree[root].pd);
    tree[root].mul = 1;
  }
  inline void buildtree(int root, int l, int r) {
    tree[root].l = l;
    tree[root].r = r;
    tree[root].mul = 1;
    if (l == r) {
      tree[root].val = ary[l];
      int sq = sqrt(ary[l]);
      for (register int i = 1; i <= (int)sq; ++i) {
        if (ary[l] % i == 0) {
          if (!is_p[i]) tree[root].factor[Set[i]] = 1;
          if (!is_p[ary[l] / i]) tree[root].factor[Set[ary[l] / i]] = 1;
        }
      }
      return;
    }
    buildtree((root << 1), l, ((tree[root].l + tree[root].r) >> 1));
    buildtree((root << 1 | 1), ((tree[root].l + tree[root].r) >> 1) + 1, r);
    update(root);
  }
  inline void mul(int root, int l, int r, int k) {
    if (l <= tree[root].l && tree[root].r <= r) {
      tree[root].mul = tree[root].mul * 1ll * k % MOD;
      tree[root].val =
          tree[root].val * 1ll * qpow(k, tree[root].r - tree[root].l + 1) % MOD;
      tree[root].pd |= prm;
      tree[root].factor |= prm;
      return;
    }
    pushdown(root);
    if (l <= ((tree[root].l + tree[root].r) >> 1)) mul((root << 1), l, r, k);
    if (((tree[root].l + tree[root].r) >> 1) < r) mul((root << 1 | 1), l, r, k);
    update(root);
  }
  inline int sum(int root, int l, int r) {
    if (l <= tree[root].l && tree[root].r <= r) {
      qry |= tree[root].factor;
      return tree[root].val;
    }
    pushdown(root);
    int ret = 1;
    if (l <= ((tree[root].l + tree[root].r) >> 1))
      ret = ret * 1ll * sum((root << 1), l, r) % MOD;
    if (((tree[root].l + tree[root].r) >> 1) < r)
      ret = ret * 1ll * sum((root << 1 | 1), l, r) % MOD;
    return ret;
  }
  inline int query(int l, int r) {
    qry.reset();
    long long mm = sum(1, l, r);
    for (register int i = 0; i <= (int)prime.size() - 1; ++i) {
      if (qry[i]) {
        (mm *= (prime[i] - 1) * 1ll * fmul[prime[i]] % MOD) %= MOD;
      }
    }
    return mm;
  }
} Tree;
inline void init() {
  for (register int i = 2; i <= (int)300; ++i) {
    if (!is_p[i]) prime.push_back(i);
    for (auto j : prime) {
      if (i * j > 300) break;
      is_p[i * j] = true;
      if (i % j == 0) break;
    }
  }
  int tot = 0;
  for (auto p : prime) {
    Set[p] = tot;
    ++tot;
  }
  is_p[1] = true;
  for (register int i = 2; i <= (int)300; ++i) {
    fmul[i] = qpow(i, MOD - 2);
  }
}
char s[32];
int main() {
  init();
  int n, m, l, r, x;
  read(n), read(m);
  for (register int i = 1; i <= (int)n; ++i) {
    read(ary[i]);
  }
  Tree.buildtree(1, 1, n);
  while (m--) {
    scanf("%s", s);
    switch (s[0]) {
      case 'T':
        read(l), read(r), print(Tree.query(l, r)), puts("");
        break;
      case 'M':
        read(l), read(r), read(x), Tree.solve(x), Tree.mul(1, l, r, x);
        break;
    }
  }
  return 0;
}
