#include <bits/stdc++.h>
using namespace std;
inline long long read() {
  long long x = 0, f = 1, ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x * f;
}
inline void write(long long x) {
  if (x < 0) putchar('-'), x = -x;
  if (x >= 10) write(x / 10);
  putchar(x % 10 + '0');
}
inline void writeln(long long x) {
  write(x);
  puts("");
}
const long long N = 1e5 + 5;
long long bin[12], n, q, A[N];
inline void init() {
  n = read();
  q = read();
  for (long long i = 1; i <= n; i++) {
    A[i] = read();
  }
}
struct node {
  long long same, plu, cov1, cov2, grade, need;
} a[N << 2];
inline pair<long long, long long> Get(long long x) {
  for (long long i = 1; i <= 11; i++) {
    if (bin[i] > x) return make_pair(i - 1, bin[i] - x);
  }
}
inline void pushup(long long k) {
  a[k].need = min(a[k << 1 | 1].need, a[k << 1].need);
  a[k].grade = min(a[k << 1].grade, a[k << 1 | 1].grade);
  a[k].same = (a[k << 1].same && a[k << 1 | 1].same &&
               a[k << 1].grade == a[k << 1 | 1].grade &&
               a[k << 1].need == a[k << 1 | 1].need);
}
void build(long long k, long long l, long long r) {
  a[k].cov1 = a[k].cov2 = -1;
  if (l == r) {
    a[k].same = 1;
    pair<long long, long long> tmp = Get(A[l]);
    a[k].grade = tmp.first;
    a[k].need = tmp.second;
    return;
  }
  long long mid = (l + r) >> 1;
  build(k << 1, l, mid);
  build(k << 1 | 1, mid + 1, r);
  pushup(k);
}
inline long long get(long long x, long long y) { return bin[x + 1] - y; }
inline void cover(long long k, long long x, long long y) {
  a[k].grade = a[k].cov1 = x;
  a[k].need = a[k].cov2 = y;
  a[k].plu = 0;
}
inline void Plus(long long k, long long z) {
  a[k].need -= z;
  a[k].plu += z;
}
inline void pushdown(long long k) {
  if (~a[k].cov1) {
    cover(k << 1, a[k].cov1, a[k].cov2);
    cover(k << 1 | 1, a[k].cov1, a[k].cov2);
    a[k].cov1 = a[k].cov2 = -1;
  }
  if (a[k].plu) {
    Plus(k << 1, a[k].plu);
    Plus(k << 1 | 1, a[k].plu);
    a[k].plu = 0;
  }
}
long long query(long long k, long long l, long long r, long long x) {
  if (l == r || a[k].same) return get(a[k].grade, a[k].need);
  long long mid = (l + r) >> 1;
  pushdown(k);
  if (mid >= x)
    return query(k << 1, l, mid, x);
  else
    return query(k << 1 | 1, mid + 1, r, x);
}
void update1(long long k, long long l, long long r, long long x, long long y,
             long long z) {
  if (l == x && r == y) {
    pair<long long, long long> tmp = Get(z);
    cover(k, tmp.first, tmp.second);
    return;
  }
  long long mid = (l + r) >> 1;
  pushdown(k);
  if (mid >= y)
    update1(k << 1, l, mid, x, y, z);
  else if (mid < x)
    update1(k << 1 | 1, mid + 1, r, x, y, z);
  else
    update1(k << 1, l, mid, x, mid, z),
        update1(k << 1 | 1, mid + 1, r, mid + 1, y, z);
  pushup(k);
}
bool update2(long long k, long long l, long long r, long long x, long long y,
             long long z) {
  if (l == x && r == y) {
    long long ans;
    if (a[k].same) {
      pair<long long, long long> tmp = Get(get(a[k].grade, a[k].need) + z);
      cover(k, tmp.first, tmp.second);
      return a[k].need == bin[tmp.first + 1] - bin[tmp.first];
    }
    if (a[k].need <= z) {
      long long mid = (l + r) >> 1;
      pushdown(k);
      ans = update2(k << 1, l, mid, x, mid, z) |
            update2(k << 1 | 1, mid + 1, r, mid + 1, y, z);
      pushup(k);
    } else {
      Plus(k, z);
      ans = 0;
    }
    return ans;
  }
  long long mid = (l + r) >> 1, ans;
  pushdown(k);
  if (mid >= y)
    ans = update2(k << 1, l, mid, x, y, z);
  else if (mid < x)
    ans = update2(k << 1 | 1, mid + 1, r, x, y, z);
  else
    ans = update2(k << 1, l, mid, x, mid, z) |
          update2(k << 1 | 1, mid + 1, r, mid + 1, y, z);
  pushup(k);
  return ans;
}
inline void solve() {
  bin[0] = 1;
  for (long long i = 1; i <= 11; i++) {
    bin[i] = bin[i - 1] * 42;
  }
  build(1, 1, n);
  for (long long i = 1; i <= q; i++) {
    long long opt = read(), x = read(), y, z;
    if (opt == 1) writeln(query(1, 1, n, x));
    if (opt == 2) {
      y = read();
      z = read();
      update1(1, 1, n, x, y, z);
    }
    if (opt == 3) {
      y = read();
      z = read();
      while (update2(1, 1, n, x, y, z))
        ;
    }
  }
}
signed main() {
  init();
  solve();
  return 0;
}
