#include <bits/stdc++.h>
using namespace std;
int set_bit(int mask, int c) { return mask |= (1UL << c); }
bool get_bit(int mask, int c) { return (mask >> c) & 1U; }
int fx[] = {1, -1, 0, 0};
int fy[] = {0, 0, 1, -1};
struct TYPE {
  int w = 0, value = 0, cnt[10000 + 5];
  bool operator<(const TYPE& a) const { return this->w < a.w; }
};
const long long MAX = 1e5 + 5, INF = 1e17, MOD = 1e9 + 7;
int KASE;
int n, block_size, arr[MAX];
vector<int> numbers;
bool lucky_number[MAX];
TYPE* block;
void generate_lucky_number(long long num) {
  if (1e4 < num) return;
  if (num) numbers.emplace_back(num);
  lucky_number[num] = true;
  generate_lucky_number((num * 10) + 4);
  generate_lucky_number((num * 10) + 7);
}
int block_id(int index) { return (index / block_size); }
int start_index_of_block(int id) { return (block_size * id); }
int end_index_of_block(int id) {
  return min((block_size * id) + block_size - 1, n - 1);
}
void build() {
  block_size = sqrt(n);
  block = new TYPE[block_size + 5];
  for (int i = 0, j = 0, cnt = 0; i < n; i++, cnt++) {
    if (block_size <= cnt) cnt = 0, j++;
    block[j].cnt[arr[i]]++;
  }
}
int query(int l, int r) {
  int ret = 0, l_b = block_id(l), r_b = block_id(r);
  if (l_b == r_b) {
    for (int i = l; i <= r; i++) {
      ret += lucky_number[arr[i] + block[l_b].value];
    }
    return ret;
  }
  int end_idx = end_index_of_block(l_b);
  for (int i = l; i <= end_idx; i++) {
    ret += lucky_number[arr[i] + block[l_b].value];
  }
  for (int i = l_b + 1; i < r_b; i++) {
    for (int j = 0; j < numbers.size(); j++) {
      if (numbers[j] - block[i].value < 0) continue;
      ret += block[i].cnt[numbers[j] - block[i].value];
    }
  }
  int start_idx = start_index_of_block(r_b);
  for (int i = start_idx; i <= r; i++) {
    ret += lucky_number[arr[i] + block[r_b].value];
  }
  return ret;
}
void update(int l, int r, int value) {
  int l_b = block_id(l), r_b = block_id(r);
  if (l_b == r_b) {
    for (int i = l; i <= r; i++) {
      block[l_b].cnt[arr[i]]--;
      arr[i] += value;
      block[l_b].cnt[arr[i]]++;
    }
    return;
  }
  int end_idx = end_index_of_block(l_b);
  for (int i = l; i <= end_idx; i++) {
    block[l_b].cnt[arr[i]]--;
    arr[i] += value;
    block[l_b].cnt[arr[i]]++;
  }
  for (int i = l_b + 1; i < r_b; i++) {
    block[i].value += value;
  }
  int start_idx = start_index_of_block(r_b);
  for (int i = start_idx; i <= r; i++) {
    block[r_b].cnt[arr[i]]--;
    arr[i] += value;
    block[r_b].cnt[arr[i]]++;
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  generate_lucky_number(0);
  int t = 1;
  for (KASE = 1; KASE <= t; KASE++) {
    int q, l, r, value, last_ans = 0;
    string type;
    cin >> n >> q;
    for (int i = 0; i < n; i++) {
      cin >> arr[i];
    }
    build();
    while (q--) {
      cin >> type >> l >> r;
      if (type == "add") {
        cin >> value;
        update(l - 1, r - 1, value);
      } else {
        last_ans = query(l - 1, r - 1);
        cout << last_ans << "\n";
      }
    }
  }
  return 0;
}
