#include <bits/stdc++.h>
using namespace std;
struct NODE {
  int v;
  bitset<62> p;
};
int n, q, l, r, x;
char g[10];
vector<int> prime;
vector<int> inversePrime;
vector<NODE> segmentTree;
vector<NODE> updateTree;
int mul(int z, int y) { return (1LL * z * y) % 1000000007; }
int power(int z, int p) {
  int y = 1;
  while (true) {
    if (p % 2 != 0) {
      y = mul(y, z);
      p--;
    }
    if (p == 0) break;
    z = mul(z, z);
    p /= 2;
  }
  return y % 1000000007;
}
void seive() {
  bitset<301> flag;
  flag.set();
  for (int i = 2; i < 301; i += 2) {
    if (flag[i]) {
      prime.push_back(i);
      for (int j = i * i; j < 301; j += i + i) {
        flag[j] = false;
      }
    }
    if (i == 2) i--;
  }
}
void inversePrimeMaker() {
  inversePrime.resize(62);
  for (int i = 0; i < 62; i++) {
    inversePrime[i] = power(prime[i], 1000000007 - 2);
  }
}
NODE setSegmentTree(vector<int> &a, int node, int left, int right) {
  if (left == right) {
    segmentTree[node].v = a[left];
    for (int i = 0; i < 62; i++) {
      if (a[left] % prime[i] == 0) {
        segmentTree[node].p[i] = true;
      }
    }
  } else {
    NODE x = setSegmentTree(a, 2 * node + 1, left, (left + right) / 2);
    NODE y = setSegmentTree(a, 2 * node + 2, ((left + right) / 2) + 1, right);
    segmentTree[node].v = (int)((1LL * x.v * y.v) % 1000000007);
    segmentTree[node].p = x.p | y.p;
  }
  return segmentTree[node];
}
void createTree(vector<int> &arr) {
  int sz = ceil(log(n) / log(2));
  sz = 2 * pow(2, sz) - 1;
  segmentTree.resize(sz);
  updateTree.resize(sz);
  for (int i = 0; i < sz; i++) {
    updateTree[i].v = 1;
    updateTree[i].p.reset();
  }
  setSegmentTree(arr, 0, 0, n - 1);
}
void checkUpdate(int node, int arrLeft, int arrRight) {
  if (updateTree[node].v != 1) {
    int nodePower = arrRight - arrLeft + 1;
    segmentTree[node].v =
        mul(segmentTree[node].v, power(updateTree[node].v, nodePower));
    segmentTree[node].p |= updateTree[node].p;
    if (arrLeft != arrRight) {
      updateTree[2 * node + 1].v =
          mul(updateTree[2 * node + 1].v, updateTree[node].v);
      updateTree[2 * node + 1].p |= updateTree[node].p;
      updateTree[2 * node + 2].v =
          mul(updateTree[2 * node + 2].v, updateTree[node].v);
      updateTree[2 * node + 2].p |= updateTree[node].p;
    }
    updateTree[node].v = 1;
    updateTree[node].p.reset();
  }
}
void multiplyX(bitset<62> &xPrime, int node, int arrLeft, int arrRight) {
  if (r < arrLeft || l > arrRight) {
    return;
  }
  checkUpdate(node, arrLeft, arrRight);
  if (l <= arrLeft && r >= arrRight) {
    updateTree[node].v = x;
    updateTree[node].p |= xPrime;
    return;
  } else {
    multiplyX(xPrime, 2 * node + 1, arrLeft, (arrLeft + arrRight) / 2);
    multiplyX(xPrime, 2 * node + 2, (arrLeft + arrRight) / 2 + 1, arrRight);
    int xPower = min(arrRight, r) - max(arrLeft, l) + 1;
    segmentTree[node].v = mul(segmentTree[node].v, power(x, xPower));
    segmentTree[node].p =
        segmentTree[2 * node + 1].p | segmentTree[2 * node + 2].p;
    segmentTree[node].p |=
        updateTree[2 * node + 1].p | updateTree[2 * node + 2].p;
    return;
  }
}
NODE getNode(int node, int arrLeft, int arrRight) {
  if (r < arrLeft || l > arrRight) {
    NODE garbage;
    garbage.v = 1, garbage.p.reset();
    return garbage;
  }
  checkUpdate(node, arrLeft, arrRight);
  if (l <= arrLeft && r >= arrRight) {
    return segmentTree[node];
  } else {
    NODE x = getNode(2 * node + 1, arrLeft, (arrLeft + arrRight) / 2);
    NODE y = getNode(2 * node + 2, (arrLeft + arrRight) / 2 + 1, arrRight);
    NODE z;
    z.v = mul(x.v, y.v);
    z.p = x.p | y.p;
    return z;
  }
}
int main() {
  seive();
  inversePrimeMaker();
  scanf("%d%d%c", &n, &q, &g[0]);
  vector<int> arr(n);
  for (int i = 0; i < n; i++) scanf("%d", &arr[i]);
  scanf("%c", &g[0]);
  createTree(arr);
  bitset<62> xPrime;
  while (q--) {
    scanf("%s%d%d", g, &l, &r);
    l--, r--;
    if (g[0] == 'M') {
      scanf("%d%c", &x, &g[0]);
      xPrime.reset();
      for (int i = 0; i < 62; i++) {
        if (x % prime[i] == 0) xPrime[i] = true;
      }
      multiplyX(xPrime, 0, 0, n - 1);
    } else {
      NODE ansNode = getNode(0, 0, n - 1);
      for (int i = 0; i < 62; i++) {
        if (ansNode.p[i]) {
          ansNode.v = mul(ansNode.v, prime[i] - 1);
          ansNode.v = mul(ansNode.v, inversePrime[i]);
        }
      }
      printf("%d\n", ansNode.v);
    }
  }
  return 0;
}
