#include <bits/stdc++.h>
using namespace std;
int read() {
  int x = 0, f = 1;
  char ch = getchar();
  while (ch - '0' < 0 || ch - '0' > 9) {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch - '0' >= 0 && ch - '0' <= 9) {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x * f;
}
int n, Q;
int a[100010];
struct Segment_Tree {
  long long dis[100010 * 4], up[100010 * 4], tag[100010 * 4];
  int eq[100010 * 4];
  void update(int k) {
    dis[k] = max(dis[k * 2], dis[k * 2 + 1]);
    up[k] = max(up[k * 2], up[k * 2 + 1]);
    eq[k] = (eq[k * 2] && eq[k * 2 + 1] && dis[k * 2] == dis[k * 2 + 1] &&
             up[k * 2] == up[k * 2 + 1] && tag[k * 2] == tag[k * 2 + 1]);
  }
  void pushdown(int k) {
    if (!eq[k]) {
      dis[k * 2] += tag[k];
      dis[k * 2 + 1] += tag[k];
      tag[k * 2] += tag[k];
      tag[k * 2 + 1] += tag[k];
      tag[k] = 0;
    } else {
      long long tmp = dis[k] + up[k];
      up[k] = 1;
      while (up[k] < tmp) up[k] *= 42;
      dis[k] = dis[k * 2] = dis[k * 2 + 1] = tmp - up[k];
      tag[k] = tag[k * 2] = tag[k * 2 + 1] = 0;
      up[k * 2] = up[k * 2 + 1] = up[k];
      eq[k * 2] = eq[k * 2 + 1] = 1;
    }
  }
  void build(int k, int l, int r) {
    if (l == r) {
      up[k] = 1;
      while (up[k] < a[l]) up[k] *= 42;
      dis[k] = a[l] - up[k];
      eq[k] = 1;
      return;
    }
    int mid = (l + r) / 2;
    build(k * 2, l, mid);
    build(k * 2 + 1, mid + 1, r);
    update(k);
  }
  void cover(int k, int l, int r, int x, int y, int z) {
    if (l >= x && r <= y) {
      tag[k] = 0;
      eq[k] = up[k] = 1;
      while (up[k] < z) up[k] *= 42;
      dis[k] = z - up[k];
      return;
    }
    pushdown(k);
    int mid = (l + r) / 2;
    if (mid >= x) cover(k * 2, l, mid, x, y, z);
    if (mid < y) cover(k * 2 + 1, mid + 1, r, x, y, z);
    update(k);
  }
  void modi(int k, int l, int r, int x, int y, int z) {
    if (l >= x && r <= y) {
      if (eq[k]) {
        long long tmp = up[k] + dis[k] + z;
        up[k] = 1;
        while (up[k] < tmp) up[k] *= 42;
        dis[k] = tmp - up[k];
      } else {
        tag[k] += z;
        dis[k] += z;
      }
      return;
    }
    pushdown(k);
    int mid = (l + r) / 2;
    if (mid >= x) modi(k * 2, l, mid, x, y, z);
    if (mid < y) modi(k * 2 + 1, mid + 1, r, x, y, z);
    update(k);
  }
  void upgrade(int k, int l, int r) {
    if (dis[k] <= 0) return;
    if (l == r) {
      long long tmp = dis[k] + up[k];
      up[k] = 1;
      while (up[k] < tmp) up[k] *= 42;
      dis[k] = tmp - up[k];
      return;
    }
    pushdown(k);
    int mid = (l + r) / 2;
    upgrade(k * 2, l, mid);
    upgrade(k * 2 + 1, mid + 1, r);
    update(k);
  }
  long long query(int k, int l, int r, int x) {
    if (l == r) return dis[k] + up[k];
    pushdown(k);
    int mid = (l + r) / 2;
    if (mid >= x)
      return query(k * 2, l, mid, x);
    else
      return query(k * 2 + 1, mid + 1, r, x);
  }
} S;
int main() {
  n = read();
  Q = read();
  for (int i = 1; i <= n; i++) a[i] = read();
  S.build(1, 1, n);
  while (Q--) {
    int op = read();
    if (op == 1) {
      int x = read();
      printf("%lld\n", S.query(1, 1, n, x));
    }
    if (op == 2) {
      int l = read(), r = read(), x = read();
      S.cover(1, 1, n, l, r, x);
    }
    if (op == 3) {
      int l = read(), r = read(), x = read();
      S.modi(1, 1, n, l, r, x);
      S.upgrade(1, 1, n);
      while (!S.dis[1]) {
        S.modi(1, 1, n, l, r, x);
        S.upgrade(1, 1, n);
      }
    }
  }
  return 0;
}
