#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int arr[N];
long long seg[N << 2], mn[N << 2], lazy[N << 2];
bool flag[N << 2];
int n, q;
vector<long long> v;
void push_down(int id) {
  if (flag[id]) {
    lazy[id] = lazy[((id << 1) + 1)] = lazy[((id << 1) + 2)] = 0;
    seg[((id << 1) + 1)] = seg[((id << 1) + 2)] = seg[id];
    mn[((id << 1) + 1)] = mn[((id << 1) + 2)] = mn[id];
    flag[((id << 1) + 1)] = flag[((id << 1) + 2)] = flag[id];
    flag[id] = 0;
  } else {
    lazy[((id << 1) + 1)] += lazy[id];
    lazy[((id << 1) + 2)] += lazy[id];
    mn[((id << 1) + 1)] -= lazy[id];
    mn[((id << 1) + 2)] -= lazy[id];
    if (seg[((id << 1) + 1)] != -1) {
      seg[((id << 1) + 1)] += lazy[id];
    }
    if (seg[((id << 1) + 2)] != -1) {
      seg[((id << 1) + 2)] += lazy[id];
    }
    lazy[id] = 0;
  }
}
void push_up(int id) {
  mn[id] = min(mn[((id << 1) + 1)], mn[((id << 1) + 2)]);
  if (seg[((id << 1) + 1)] == seg[((id << 1) + 2)]) {
    seg[id] = seg[((id << 1) + 1)];
  } else {
    seg[id] = -1;
  }
}
void build(int id = 0, int s = 0, int e = n) {
  if (s + 1 == e) {
    seg[id] = arr[s];
    mn[id] = *upper_bound(v.begin(), v.end(), arr[s]) - arr[s];
    return;
  }
  int mid = (s + e) >> 1;
  build(((id << 1) + 1), s, mid);
  build(((id << 1) + 2), mid, e);
  push_up(id);
}
void print(int id = 0, int s = 0, int e = n) {
  cout << "[" << s + 1 << "," << e << "] " << id << " == > " << mn[id] << " "
       << seg[id] << endl;
  if (s + 1 == e) {
    return;
  }
  push_down(id);
  int mid = (s + e) >> 1;
  print(((id << 1) + 1), s, mid);
  print(((id << 1) + 2), mid, e);
  push_up(id);
}
long long query(int l, int r, int id = 0, int s = 0, int e = n) {
  if (l >= e || r <= s) return 0;
  if (s + 1 == e) return seg[id];
  push_down(id);
  int mid = (s + e) >> 1;
  long long ret = query(l, r, ((id << 1) + 1), s, mid) +
                  query(l, r, ((id << 1) + 2), mid, e);
  push_up(id);
  return ret;
}
void Set(int l, int r, int x, int id = 0, int s = 0, int e = n) {
  if (l >= e || r <= s) return;
  if (l <= s && r >= e) {
    seg[id] = x;
    flag[id] = true;
    mn[id] = (*lower_bound(v.begin(), v.end(), x)) - x;
    lazy[id] = 0;
    return;
  }
  push_down(id);
  int mid = (s + e) >> 1;
  Set(l, r, x, ((id << 1) + 1), s, mid);
  Set(l, r, x, ((id << 1) + 2), mid, e);
  push_up(id);
}
void add(int l, int r, int x, int id = 0, int s = 0, int e = n) {
  if (l >= e || r <= s) return;
  if (l <= s && r >= e) {
    if (seg[id] != -1) {
      seg[id] += x;
      mn[id] = (*lower_bound(v.begin(), v.end(), seg[id])) - seg[id];
      flag[id] = true;
      lazy[id] = 0;
      return;
    } else if (mn[id] >= x) {
      mn[id] -= x;
      lazy[id] += x;
      return;
    }
  }
  push_down(id);
  int mid = (s + e) >> 1;
  add(l, r, x, ((id << 1) + 1), s, mid);
  add(l, r, x, ((id << 1) + 2), mid, e);
  push_up(id);
}
int main() {
  v.push_back(1);
  while (v.back() < 1e17) {
    v.push_back(v.back() * 42);
  }
  scanf("%d%d", &n, &q);
  for (int i = 0; i < n; i++) scanf("%d", &arr[i]);
  int type, a, b, x;
  build();
  while (q--) {
    scanf("%d", &type);
    if (type == 1) {
      scanf("%d", &a);
      printf("%lld\n", query(a - 1, a));
    } else if (type == 2) {
      scanf("%d%d%d", &a, &b, &x);
      Set(a - 1, b, x);
    } else {
      scanf("%d%d%d", &a, &b, &x);
      do {
        add(a - 1, b, x);
      } while (mn[0] == 0);
    }
  }
  return 0;
}
