#include <bits/stdc++.h>
using namespace std;
const long long maxn = 100005, maxk = maxn << 2, maxp = 13;
long long n, cnt, q;
long long a[maxn], pw[maxp], minn[maxk], lc[maxk], rc[maxk], lazyval[maxk],
    lazyadd[maxk], nxt[maxn];
set<long long> s;
inline long long get(long long x) { return *lower_bound(pw, pw + 12, x); }
inline void pushup(long long now) {
  minn[now] = min(minn[lc[now]], minn[rc[now]]);
}
inline void getval(long long now, long long v) { minn[now] = lazyval[now] = v; }
inline void getadd(long long now, long long v) {
  minn[now] += v, lazyadd[now] += v;
}
inline void pushdown(long long now) {
  if (lazyval[now])
    getval(lc[now], lazyval[now]), getval(rc[now], lazyval[now]),
        lazyval[now] = 0;
  if (lazyadd[now])
    getadd(lc[now], lazyadd[now]), getadd(rc[now], lazyadd[now]),
        lazyadd[now] = 0;
}
void build(long long l, long long r, long long now) {
  if (l == r) {
    nxt[l] = get(a[l]), minn[now] = nxt[l] - a[l];
    return;
  }
  long long mid = (l + r) >> 1;
  lc[now] = now << 1, rc[now] = now << 1 | 1;
  build(l, mid, lc[now]), build(mid + 1, r, rc[now]);
  pushup(now);
}
void updval(long long l, long long r, long long now, long long L, long long R) {
  if (L <= l && r <= R) {
    getval(now, 1000000000000000000ll);
    return;
  }
  long long mid = (l + r) >> 1;
  pushdown(now);
  if (L <= mid) updval(l, mid, lc[now], L, R);
  if (mid < R) updval(mid + 1, r, rc[now], L, R);
  pushup(now);
}
void updadd(long long l, long long r, long long now, long long L, long long R,
            long long v) {
  if (L <= l && r <= R) {
    getadd(now, v);
    return;
  }
  long long mid = (l + r) >> 1;
  pushdown(now);
  if (L <= mid) updadd(l, mid, lc[now], L, R, v);
  if (mid < R) updadd(mid + 1, r, rc[now], L, R, v);
  pushup(now);
}
void modify(long long l, long long r, long long now, long long pos,
            long long v) {
  if (l == r) {
    nxt[l] = get(v), minn[now] = nxt[l] - v;
    return;
  }
  long long mid = (l + r) >> 1;
  pushdown(now);
  if (pos <= mid)
    modify(l, mid, lc[now], pos, v);
  else
    modify(mid + 1, r, rc[now], pos, v);
  pushup(now);
}
void check(long long l, long long r, long long now) {
  if (minn[now] > 0) return;
  if (l == r) {
    long long v = nxt[l] - minn[now];
    nxt[l] = get(v), minn[now] = nxt[l] - v;
    return;
  }
  long long mid = (l + r) >> 1;
  pushdown(now);
  check(l, mid, lc[now]), check(mid + 1, r, rc[now]);
  pushup(now);
}
long long query(long long l, long long r, long long now, long long pos) {
  if (l == r) return nxt[l] - minn[now];
  pushdown(now);
  long long mid = (l + r) >> 1;
  if (pos <= mid) return query(l, mid, lc[now], pos);
  return query(mid + 1, r, rc[now], pos);
}
void trans(long long pos) {
  long long lst = *s.lower_bound(pos);
  if (pos == 0 || lst == pos) return;
  nxt[pos] = nxt[lst], s.insert(pos), modify(1, n, 1, pos, query(1, n, 1, lst));
}
signed main() {
  pw[0] = 1;
  for (long long i = 1; i <= 11; i++) pw[i] = pw[i - 1] * 42ll;
  pw[12] = 1000000000000000000ll;
  scanf("%lld%lld", &n, &q);
  for (long long i = 1; i <= n; i++) scanf("%lld", &a[i]), s.insert(i);
  build(1, n, 1);
  while (q--) {
    long long opt, l, r, x;
    scanf("%lld", &opt);
    if (opt == 1) {
      scanf("%lld", &x);
      printf("%lld\n", query(1, n, 1, *s.lower_bound(x)));
    }
    if (opt == 2) {
      scanf("%lld%lld%lld", &l, &r, &x);
      trans(l - 1), trans(r);
      if (l < r) updval(1, n, 1, l, r - 1);
      modify(1, n, 1, r, x);
      s.erase(s.lower_bound(l), s.lower_bound(r));
    }
    if (opt == 3) {
      scanf("%lld%lld%lld", &l, &r, &x);
      trans(l - 1), trans(r);
      updadd(1, n, 1, l, r, -x), check(1, n, 1);
      while (minn[1] == 0) updadd(1, n, 1, l, r, -x), check(1, n, 1);
    }
  }
  return 0;
}
