#include <bits/stdc++.h>
using namespace std;
inline void rd(int &x) {
  char ch;
  x = 0;
  bool fl = false;
  while (!isdigit(ch = getchar())) (ch == '-') && (fl = true);
  for (x = (ch ^ '0'); isdigit(ch = getchar()); x = x * 10 + (ch ^ '0'))
    ;
  (fl == true) && (x = -x);
}
namespace Miracle {
const int N = 100000 + 5;
const long long inf = 0x3f3f3f3f3f3f3f3f;
int n, q;
int U;
long long a[N];
long long mi[11];
pair<long long, long long> zip(long long x) {
  int p = lower_bound(mi, mi + U + 1, x) - mi;
  --p;
  return make_pair(p, x - mi[p + 1]);
}
long long num(int lev, long long dis) { return mi[lev + 1] + dis; }
struct tr {
  long long mx;
  long long ad, chan;
  int same;
  int lev;
  long long val;
} t[4 * N];
void pushup(int x) {
  t[x].mx = max(t[x << 1].mx, t[x << 1 | 1].mx);
  if (t[x << 1].same && t[x << 1 | 1].same &&
      t[x << 1].val == t[x << 1 | 1].val &&
      t[x << 1].lev == t[x << 1 | 1].lev) {
    t[x].same = 1;
    t[x].val = t[x << 1].val;
    t[x].lev = t[x << 1].lev;
  } else {
    t[x].same = 0;
  }
}
pair<long long, long long> tmp;
void pro(int &lev, long long &dis) {
  long long now = num(lev, dis);
  tmp = zip(now);
  lev = tmp.first;
  dis = tmp.second;
}
void build(int x, int l, int r) {
  if (l == r) {
    t[x].same = 1;
    tmp = zip(a[l]);
    t[x].mx = t[x].val = tmp.second;
    t[x].lev = tmp.first;
    t[x].chan = -inf;
    t[x].ad = 0;
    return;
  }
  t[x].ad = 0;
  t[x].chan = -inf;
  build((x << 1), l, ((l + r) >> 1));
  build((x << 1 | 1), ((l + r) >> 1) + 1, r);
  pushup(x);
}
void pushdown(int x) {
  for (register int i = 0; i <= 1; ++i) {
    int son = x << 1 | i;
    if (t[x].chan != -inf) {
      long long c = t[x].chan;
      t[son].same = 1;
      tmp = zip(c);
      t[son].lev = tmp.first;
      t[son].val = tmp.second;
      t[son].ad = 0;
      t[son].chan = c;
      t[son].mx = t[son].val;
    } else if (t[x].ad) {
      long long c = t[x].ad;
      if (t[son].same) {
        if (t[son].chan != -inf) {
          t[son].chan += c;
        } else {
          t[son].ad += c;
        }
        t[son].val += c;
        pro(t[son].lev, t[son].val);
        t[son].mx = t[son].val;
      } else {
        t[son].mx += c;
        t[son].ad += c;
      }
    }
  }
  t[x].ad = 0;
  t[x].chan = -inf;
}
bool upda(int x, int l, int r) {
  if (l == r) {
    if (t[x].val == 0) {
      return true;
    }
    return false;
  } else if (t[x].same) {
    if (t[x].val == 0) return true;
    return false;
  }
  pushdown(x);
  bool ret = false;
  if (t[(x << 1)].mx >= 0) ret |= upda(x << 1, l, ((l + r) >> 1));
  if (t[(x << 1 | 1)].mx >= 0) ret |= upda(x << 1 | 1, ((l + r) >> 1) + 1, r);
  pushup(x);
  return ret;
}
int flag;
void add(int x, int l, int r, int L, int R, long long c) {
  if (L <= l && r <= R) {
    if (t[x].same) {
      if (t[x].chan != -inf) {
        t[x].chan += c;
      } else {
        t[x].ad += c;
      }
      t[x].val += c;
      pro(t[x].lev, t[x].val);
      t[x].mx = t[x].val;
      if (t[x].mx == 0) flag = 1;
    } else {
      t[x].mx += c;
      t[x].ad += c;
      if (t[x].mx >= 0) {
        flag |= upda(x, l, r);
      }
    }
    return;
  }
  pushdown(x);
  if (L <= ((l + r) >> 1)) add(x << 1, l, ((l + r) >> 1), L, R, c);
  if (((l + r) >> 1) < R) add(x << 1 | 1, ((l + r) >> 1) + 1, r, L, R, c);
  pushup(x);
}
void chan(int x, int l, int r, int L, int R, long long c) {
  if (L <= l && r <= R) {
    t[x].same = 1;
    tmp = zip(c);
    t[x].lev = tmp.first;
    t[x].val = tmp.second;
    t[x].ad = 0;
    t[x].chan = c;
    t[x].mx = t[x].val;
    return;
  }
  pushdown(x);
  if (L <= ((l + r) >> 1)) chan(x << 1, l, ((l + r) >> 1), L, R, c);
  if (((l + r) >> 1) < R) chan(x << 1 | 1, ((l + r) >> 1) + 1, r, L, R, c);
  pushup(x);
}
long long query(int x, int l, int r, int p) {
  if (l == r) {
    return num(t[x].lev, t[x].val);
  }
  pushdown(x);
  if (p <= ((l + r) >> 1))
    return query((x << 1), l, ((l + r) >> 1), p);
  else
    return query((x << 1 | 1), ((l + r) >> 1) + 1, r, p);
}
int main() {
  rd(n);
  rd(q);
  for (register int i = 1; i <= n; ++i) {
    scanf("%lld", &a[i]);
  }
  mi[0] = 1;
  for (register int i = 1; i <= 10; ++i) mi[i] = mi[i - 1] * 42;
  U = 10;
  build(1, 1, n);
  int op, l, r, p;
  long long c;
  while (q--) {
    rd(op);
    if (op == 1) {
      rd(p);
      printf("%lld\n", query(1, 1, n, p));
    } else if (op == 2) {
      rd(l);
      rd(r);
      scanf("%lld", &c);
      chan(1, 1, n, l, r, c);
    } else {
      rd(l);
      rd(r);
      scanf("%lld", &c);
      flag = 0;
      add(1, 1, n, l, r, c);
      while (flag) {
        flag = 0;
        add(1, 1, n, l, r, c);
      }
    }
  }
  return 0;
}
}  // namespace Miracle
signed main() {
  Miracle::main();
  return 0;
}
