#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1e9 + 7;
const int VALMAX = 300;
vector<int> primes;
long long lgput(long long x, long long p) {
  long long ans = 1;
  while (p) {
    if (p % 2) ans = (ans * x) % MOD;
    x = (x * x) % MOD;
    p /= 2;
  }
  return ans;
}
struct AINT {
  vector<long long> aint, lazy;
  vector<long long> lazynumbers, numbers;
  AINT(int n) {
    aint.resize(4 * n + 1, 0);
    lazy.resize(4 * n + 1, 0);
    numbers.resize(4 * n + 1, 1);
    lazynumbers.resize(4 * n + 1, 1);
  }
  void buildtree(int node, int le, int ri, const vector<long long> &mask,
                 const vector<long long> &v) {
    if (le == ri) {
      aint[node] = mask[le];
      numbers[node] = v[le];
    } else {
      int mid = (le + ri) / 2;
      buildtree(node * 2, le, mid, mask, v);
      buildtree(node * 2 + 1, mid + 1, ri, mask, v);
      aint[node] = (aint[node * 2] | aint[node * 2 + 1]);
      numbers[node] = (numbers[node * 2] * numbers[node * 2 + 1]) % MOD;
    }
  }
  void update(long long mask, long long nr, int from, int to, int node, int le,
              int ri) {
    if (from <= le && ri <= to) {
      lazy[node] |= mask;
      aint[node] |= mask;
      numbers[node] = (numbers[node] * lgput(nr, ri - le + 1)) % MOD;
      lazynumbers[node] = (lazynumbers[node] * nr) % MOD;
    } else {
      int mid = (le + ri) / 2;
      if (from <= mid) update(mask, nr, from, to, node * 2, le, mid);
      if (mid < to) update(mask, nr, from, to, node * 2 + 1, mid + 1, ri);
      aint[node] = (lazy[node] | (aint[node * 2] | aint[node * 2 + 1]));
      numbers[node] = (((numbers[node * 2] * numbers[node * 2 + 1]) % MOD) *
                       lgput(lazynumbers[node], ri - le + 1)) %
                      MOD;
    }
  }
  pair<long long, long long> query(int from, int to, int node, int le, int ri) {
    if (from <= le && ri <= to) return {aint[node], numbers[node]};
    int mid = (le + ri) / 2;
    pair<long long, long long> ans = {0, 1};
    if (from <= mid) {
      ans = query(from, to, node * 2, le, mid);
    }
    if (mid < to) {
      auto aux = query(from, to, node * 2 + 1, mid + 1, ri);
      ans = {ans.first | aux.first, (ans.second * aux.second) % MOD};
    }
    ans.first |= lazy[node];
    ans.second = (ans.second *
                  lgput(lazynumbers[node], min(to, ri) - max(le, from) + 1)) %
                 MOD;
    return ans;
  }
};
long long invmod(long long x) { return lgput(x, MOD - 2); }
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  vector<bool> isprime(1 + VALMAX, 1);
  for (int i = 2; i <= VALMAX; i++)
    if (isprime[i]) {
      primes.push_back(i);
      for (int j = i; j <= VALMAX; j += i) isprime[j] = 0;
    }
  vector<long long> inv(primes.size(), 1);
  for (int i = 0; i < primes.size(); i++)
    inv[i] = ((primes[i] - 1) * invmod(primes[i])) % MOD;
  int n, q;
  cin >> n >> q;
  vector<long long> masks(n + 1, 0);
  vector<long long> v(n + 1, 0);
  for (int i = 1; i <= n; i++) {
    int x;
    cin >> x;
    v[i] = x;
    for (int j = 0; j < primes.size(); j++)
      if (x % primes[j] == 0) masks[i] ^= (1LL << j);
  }
  AINT aint(n);
  aint.buildtree(1, 1, n, masks, v);
  while (q--) {
    string s;
    cin >> s;
    if (s == "MULTIPLY") {
      int l, r, x;
      cin >> l >> r >> x;
      long long mask = 0;
      for (int j = 0; j < primes.size(); j++)
        if (x % primes[j] == 0) mask ^= (1LL << j);
      aint.update(mask, x, l, r, 1, 1, n);
    } else {
      int l, r;
      cin >> l >> r;
      auto mask = aint.query(l, r, 1, 1, n);
      long long ans = mask.second;
      for (int j = 0; j < primes.size(); j++)
        if (mask.first & (1LL << j)) ans = (ans * inv[j]) % MOD;
      cout << ans << "\n";
    }
  }
  return 0;
}
