#include <bits/stdc++.h>
using namespace std;
template <typename T>
void R(T &x) {
  x = 0;
  char ch = getchar();
  while (ch < '0' || '9' < ch) ch = getchar();
  while ('0' <= ch && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
}
void write(long long x) {
  if (x < 0) x = -x, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
inline void writeln(long long x) {
  write(x);
  puts("");
}
const int N = 110000;
int n, m;
long long a[N];
struct Tree {
  int l, r;
  long long minv, ad, num;
} tree[N << 2];
inline void update(int o) {
  while (tree[o].minv < 0)
    tree[o].minv = (tree[o].minv + tree[o].num) * 42 - tree[o].num;
}
void build(int o, int l, int r) {
  tree[o].l = l, tree[o].r = r;
  if (l == r) {
    tree[o].num = a[l];
    tree[o].minv = 1;
    while (tree[o].minv < tree[o].num) tree[o].minv *= 42;
    tree[o].minv -= tree[o].num;
    return;
  }
  int mid = (l + r) >> 1;
  if (l <= mid) build((o << 1), l, mid);
  if (r > mid) build((o << 1 | 1), mid + 1, r);
  tree[o].minv = min(tree[(o << 1)].minv, tree[(o << 1 | 1)].minv);
}
inline void pushdown(int o) {
  if (tree[o].num) {
    tree[(o << 1)].ad = tree[(o << 1 | 1)].ad = 0;
    tree[(o << 1)].num = tree[(o << 1 | 1)].num = tree[o].num;
    tree[(o << 1)].minv = tree[(o << 1 | 1)].minv = tree[o].minv;
    tree[o].num = 0;
    return;
  }
  if (tree[o].ad) {
    if (tree[(o << 1)].num) {
      tree[(o << 1)].num += tree[o].ad;
      tree[(o << 1)].minv -= tree[o].ad;
      update((o << 1));
    } else
      tree[(o << 1)].ad += tree[o].ad, tree[(o << 1)].minv -= tree[o].ad;
    if (tree[(o << 1 | 1)].num) {
      tree[(o << 1 | 1)].num += tree[o].ad;
      tree[(o << 1 | 1)].minv -= tree[o].ad;
      update((o << 1 | 1));
    } else
      tree[(o << 1 | 1)].ad += tree[o].ad,
          tree[(o << 1 | 1)].minv -= tree[o].ad;
    tree[o].ad = 0;
  }
}
long long ask(int o, int x) {
  if (tree[o].num) return tree[o].num;
  pushdown(o);
  int mid = (tree[o].l + tree[o].r) >> 1;
  if (x <= mid)
    return ask((o << 1), x);
  else
    return ask((o << 1 | 1), x);
}
void change(int o) {
  if (tree[o].num) {
    update(o);
    return;
  }
  int mid = (tree[o].l + tree[o].r) >> 1;
  pushdown(o);
  if (tree[(o << 1)].minv < 0) change((o << 1));
  if (tree[(o << 1 | 1)].minv < 0) change((o << 1 | 1));
  tree[o].minv = min(tree[(o << 1)].minv, tree[(o << 1 | 1)].minv);
}
void change3(int o, int l, int r, long long v) {
  if (tree[o].l >= l && tree[o].r <= r) {
    tree[o].minv -= v;
    if (tree[o].num)
      tree[o].num += v;
    else
      tree[o].ad += v;
    if (tree[o].minv < 0) change(o);
    return;
  }
  pushdown(o);
  int mid = (tree[o].l + tree[o].r) >> 1;
  if (l <= mid) change3((o << 1), l, r, v);
  if (r > mid) change3((o << 1 | 1), l, r, v);
  tree[o].minv = min(tree[(o << 1)].minv, tree[(o << 1 | 1)].minv);
}
void change2(int o, int l, int r, long long v, long long bb) {
  if (l <= tree[o].l && tree[o].r <= r) {
    tree[o].num = v;
    tree[o].minv = bb;
    tree[o].ad = 0;
    return;
  }
  pushdown(o);
  int mid = (tree[o].l + tree[o].r) >> 1;
  if (l <= mid) change2((o << 1), l, r, v, bb);
  if (r > mid) change2((o << 1 | 1), l, r, v, bb);
  tree[o].minv = min(tree[(o << 1)].minv, tree[(o << 1 | 1)].minv);
}
int main() {
  int opt, l, r;
  long long x;
  R(n), R(m);
  for (int i = 1; i <= n; ++i) R(a[i]);
  build(1, 1, n);
  for (int i = 1; i <= m; ++i) {
    R(opt), R(l);
    if (opt == 1)
      writeln(ask(1, l));
    else {
      R(r), R(x);
      if (opt == 2) {
        long long y = 1;
        while (y < x) y *= 42;
        change2(1, l, r, x, y - x);
      }
      if (opt == 3) {
        do {
          change3(1, l, r, x);
        } while (tree[1].minv == 0);
      }
    }
  }
  return 0;
}
