#include <bits/stdc++.h>
using namespace std;
const int maxn = 200000 + 10;
const int nn = 65536 * 2;
int n;
set<int> clef;
long long tag[nn * 2 + 10], nxt[nn * 2 + 10];
pair<long long, int> tree[nn * 2 + 10];
void val(long long &x) {
  if (x > (long long)2e18) x = (long long)2e18;
}
void cal(int x) {
  val(tag[x]);
  val(tree[x].first);
  val(nxt[x]);
}
void _down(int id) {
  tree[id * 2].first -= tag[id], tag[id * 2] += tag[id];
  tree[id * 2 + 1].first -= tag[id], tag[id * 2 + 1] += tag[id];
  cal(id * 2);
  cal(id * 2 + 1);
  tag[id] = 0;
}
void _init(int x, long long y) {
  long long op = 1;
  long long tmp = y;
  tag[x + nn - 1] = 0;
  while (tmp > op) op = op * 42;
  if (tmp == 2e18) op = 2e18;
  nxt[x + nn - 1] = op;
  tree[x + nn - 1] = make_pair(op - tmp, x);
}
long long fix;
void _update(int a, int b, int l, int r, int id) {
  if (a > r or b < l) return;
  if (l >= a and r <= b) {
    tree[id].first -= fix;
    tag[id] += fix;
    cal(id);
    return;
  }
  _down(id);
  _update(a, b, l, (l + r) / 2, id * 2);
  _update(a, b, (l + r) / 2 + 1, r, id * 2 + 1);
  tree[id] = min(tree[id * 2], tree[id * 2 + 1]);
}
void _modify(int x, int l, int r, int id) {
  if (x > r or x < l) return;
  if (x == l and x == r) {
    _init(x, fix);
    return;
  }
  _down(id);
  _modify(x, l, (l + r) / 2, id * 2);
  _modify(x, (l + r) / 2 + 1, r, id * 2 + 1);
  tree[id] = min(tree[id * 2], tree[id * 2 + 1]);
}
pair<long long, int> _query(int a, int b, int l, int r, int id) {
  if (a > r or b < l) return make_pair(2e18, -1);
  if (l >= a and r <= b) return tree[id];
  _down(id);
  return min(_query(a, b, l, (l + r) / 2, id * 2),
             _query(a, b, (l + r) / 2 + 1, r, id * 2 + 1));
}
long long _ask(int a, int b, int l, int r, int id) {
  if (a > r or b < l) return 2e18;
  if (l >= a and r <= b) return -tree[id].first + nxt[id];
  _down(id);
  return min(_ask(a, b, l, (l + r) / 2, id * 2),
             _ask(a, b, (l + r) / 2 + 1, r, id * 2 + 1));
}
void _refresh(int x) {
  int t = *clef.lower_bound(x);
  if (x == t) return;
  fix = _ask(t, t, 1, nn, 1);
  _modify(x, 1, nn, 1);
  clef.insert(x);
}
int main() {
  int Q;
  scanf("%d%d", &n, &Q);
  for (int i = 1; i <= n; i++) {
    long long tmp;
    clef.insert(i);
    scanf("%I64d", &tmp);
    fix = tmp;
    _modify(i, 1, nn, 1);
  }
  while (Q--) {
    int typ;
    scanf("%d", &typ);
    if (typ == 1) {
      int x;
      scanf("%d", &x);
      x = *(clef.lower_bound(x));
      printf("%I64d\n", _ask(x, x, 1, nn, 1));
    }
    if (typ == 3) {
      int l, r;
      long long k;
      scanf("%d%d%I64d", &l, &r, &k);
      if (l >= 1) _refresh(l - 1);
      _refresh(r);
      while (1) {
        int flag = 1;
        fix = k;
        _update(l, r, 1, nn, 1);
        while (1) {
          pair<long long, int> op = _query(l, r, 1, nn, 1);
          if (op.first == 0) flag = 0;
          if (op.first >= 0) break;
          if (op.first < 0) {
            fix = nxt[op.second + nn - 1] - op.first;
            _modify(op.second, 1, nn, 1);
          }
        }
        if (flag) break;
      }
    }
    if (typ == 2) {
      int l, r;
      long long k;
      scanf("%d%d%I64d", &l, &r, &k);
      if (l >= 1) _refresh(l - 1);
      _refresh(r);
      clef.insert(r);
      fix = k;
      _modify(r, 1, nn, 1);
      while (1) {
        set<int>::iterator it = clef.lower_bound(l);
        int op = *it;
        if (op == r) break;
        clef.erase(it);
        fix = 2e18;
        _modify(op, 1, nn, 1);
      }
    }
  }
  return 0;
}
