#include <bits/stdc++.h>
using namespace std;
const int N = 100100;
inline long long add(long long a, long long b) {
  if (a + b >= 1000000007) return a + b - 1000000007;
  return a + b;
}
long long powmod(long long a, long long b) {
  if (b == 0) return 1;
  long long x = powmod(a, b / 2);
  long long y = (x * x) % 1000000007;
  if (b % 2) return (a * y) % 1000000007;
  return y % 1000000007;
}
long long a[N], st[4 * N][6], lazy[4 * N][6], sum[N][6];
int n, m;
void make_tree(int l, int h, int root, int k) {
  if (l == h) {
    st[root][k] = (a[l] * powmod((long long)l, (long long)k)) % 1000000007;
    return;
  }
  int mid = (l + h) / 2, c1 = 2 * root + 1, c2 = 2 * root + 2;
  make_tree(l, mid, c1, k);
  make_tree(mid + 1, h, c2, k);
  st[root][k] = add(st[c1][k], st[c2][k]);
}
void update_tree(int ql, int qh, int l, int h, int root, long long val, int k) {
  if (l > h) return;
  int mid = (l + h) / 2, c1 = 2 * root + 1, c2 = 2 * root + 2;
  if (lazy[root][k]) {
    st[root][k] = (lazy[root][k] *
                   ((1000000007 + sum[h][k] - sum[l - 1][k]) % 1000000007)) %
                  1000000007;
    if (l != h) {
      lazy[c1][k] = lazy[root][k];
      lazy[c2][k] = lazy[root][k];
    }
    lazy[root][k] = 0;
  }
  if (ql > h || qh < l) return;
  if (ql <= l && qh >= h) {
    st[root][k] =
        (val * ((1000000007 + sum[h][k] - sum[l - 1][k]) % 1000000007)) %
        1000000007;
    if (l != h) {
      lazy[c1][k] = val;
      lazy[c2][k] = val;
    }
    return;
  }
  update_tree(ql, qh, l, mid, c1, val, k);
  update_tree(ql, qh, mid + 1, h, c2, val, k);
  st[root][k] = add(st[c1][k], st[c2][k]);
}
long long query_tree(int ql, int qh, int l, int h, int root, int k) {
  if (ql > h || qh < l || l > h) return 0;
  int mid = (l + h) / 2, c1 = 2 * root + 1, c2 = 2 * root + 2;
  if (lazy[root][k]) {
    st[root][k] = (lazy[root][k] *
                   ((1000000007 + sum[h][k] - sum[l - 1][k]) % 1000000007)) %
                  1000000007;
    if (l != h) {
      lazy[c1][k] = lazy[root][k];
      lazy[c2][k] = lazy[root][k];
    }
    lazy[root][k] = 0;
  }
  if (ql <= l && qh >= h) {
    return st[root][k];
  }
  return add(query_tree(ql, qh, l, mid, c1, k),
             query_tree(ql, qh, mid + 1, h, c2, k));
}
int main() {
  for (long long i = 1; i < N; i++)
    for (long long j = 0; j < 6; j++)
      sum[i][j] = add(sum[i - 1][j], powmod(i, j));
  scanf("%d", &n);
  scanf("%d", &m);
  for (long long i = 1; i < n + 1; i++) {
    int tmp;
    scanf("%d", &tmp);
    a[i] = (long long)tmp;
  }
  for (long long i = 0; i < 6; i++) make_tree(0, n, 0, i);
  while (m--) {
    char c[1];
    int l, r, dv;
    long long k;
    scanf("%s %d %d %d", c, &l, &r, &dv);
    k = (long long)dv;
    if (c[0] == '=') {
      for (long long x = 0; x < 6; x++) update_tree(l, r, 0, n, 0, k, x);
    } else {
      long long x[6];
      for (long long i = 0; i < k + 1; i++) x[i] = query_tree(l, r, 0, n, 0, i);
      if (k == 0) {
        printf("%lld\n", x[0]);
      } else if (k == 1) {
        long long ans = 0, tmp, p = l - 1;
        tmp = x[1];
        ans = (ans + tmp) % 1000000007;
        tmp = (x[0] * p) % 1000000007;
        ans = (ans + 1000000007 - tmp) % 1000000007;
        printf("%lld\n", ans);
      } else if (k == 2) {
        long long ans = 0, tmp, p = 1 - l;
        tmp = x[2];
        ans = add(ans, tmp);
        tmp = (2 * ((x[1] * p) % 1000000007)) % 1000000007;
        ans = (ans + 1000000007 + tmp) % 1000000007;
        p = (p * p) % 1000000007;
        tmp = (x[0] * p) % 1000000007;
        ans = (ans + tmp) % 1000000007;
        printf("%lld\n", ans);
      } else if (k == 3) {
        long long ans = 0, tmp, p = 1 - l;
        long long q = p;
        tmp = x[3];
        ans = add(ans, tmp);
        tmp = (3 * ((x[2] * p) % 1000000007)) % 1000000007;
        ans = (ans + 1000000007 + tmp) % 1000000007;
        p = (p * q) % 1000000007;
        tmp = (3 * ((x[1] * p) % 1000000007)) % 1000000007;
        ans = (ans + 1000000007 + tmp) % 1000000007;
        p = (p * q) % 1000000007;
        tmp = (x[0] * p) % 1000000007;
        ans = (ans + 1000000007 + tmp) % 1000000007;
        printf("%lld\n", ans);
      } else if (k == 4) {
        long long ans = 0, tmp, p = 1 - l;
        long long q = p;
        tmp = x[4];
        ans = add(ans, tmp);
        tmp = (4 * ((x[3] * p) % 1000000007)) % 1000000007;
        ans = (ans + 1000000007 + tmp) % 1000000007;
        p = (p * q) % 1000000007;
        tmp = (6 * ((x[2] * p) % 1000000007)) % 1000000007;
        ans = (ans + 1000000007 + tmp) % 1000000007;
        p = (p * q) % 1000000007;
        tmp = (4 * ((x[1] * p) % 1000000007)) % 1000000007;
        ans = (ans + 1000000007 + tmp) % 1000000007;
        p = (p * q) % 1000000007;
        tmp = (x[0] * p) % 1000000007;
        ans = (ans + 1000000007 + tmp) % 1000000007;
        printf("%lld\n", ans);
      } else {
        long long ans = 0, tmp, p = 1 - l;
        long long q = p;
        tmp = x[5];
        ans = add(ans, tmp);
        tmp = (5 * ((x[4] * p) % 1000000007)) % 1000000007;
        ans = (ans + 1000000007 + tmp) % 1000000007;
        p = (p * q) % 1000000007;
        tmp = (10 * ((x[3] * p) % 1000000007)) % 1000000007;
        ans = (ans + 1000000007 + tmp) % 1000000007;
        p = (p * q) % 1000000007;
        tmp = (10 * ((x[2] * p) % 1000000007)) % 1000000007;
        ans = (ans + 1000000007 + tmp) % 1000000007;
        p = (p * q) % 1000000007;
        tmp = (5 * ((x[1] * p) % 1000000007)) % 1000000007;
        ans = (ans + 1000000007 + tmp) % 1000000007;
        p = (p * q) % 1000000007;
        tmp = (x[0] * p) % 1000000007;
        ans = (ans + 1000000007 + tmp) % 1000000007;
        printf("%lld\n", ans);
      }
    }
  }
  return 0;
}
