#include <bits/stdc++.h>
using namespace std;
struct treenode {
  long long add, min, ord, num, sum;
};
treenode tree[500000];
int i, m, n, t, x, y, z;
inline int fastscanf() {
  int t = 0;
  char c = getchar();
  while (!((c > 47) && (c < 58))) c = getchar();
  while ((c > 47) && (c < 58)) t = t * 10 + c - 48, c = getchar();
  return t;
}
inline void resetnode_(treenode& node) {
  for (; node.min < 0;) {
    node.min = node.min + node.num - node.num / 42;
    node.sum = node.sum + node.num - node.num / 42;
    node.num = node.num * 42;
  }
  return;
}
inline treenode resetnode(int x) {
  treenode node = (treenode){0, -x, 1, 1, 0};
  resetnode_(node);
  return node;
}
inline void buildtree(int l, int r, int node) {
  if (l == r)
    tree[node] = resetnode(fastscanf());
  else {
    int mid = (l + r) >> 1;
    buildtree(l, mid, node << 1);
    buildtree(mid + 1, r, node << 1 | 1);
    tree[node].min = min(tree[node << 1].min, tree[node << 1 | 1].min);
  }
  return;
}
inline void pushdown(int l, int r, int node) {
  if (tree[node].add) {
    tree[node].min = tree[node].min - tree[node].add;
    if (l != r) {
      tree[node << 1].add = tree[node << 1].add + tree[node].add;
      tree[node << 1 | 1].add = tree[node << 1 | 1].add + tree[node].add;
    }
    tree[node].add = 0;
  }
  if (tree[node].min < 0)
    if (tree[node].ord)
      resetnode_(tree[node]);
    else {
      int mid = (l + r) >> 1;
      pushdown(l, mid, node << 1);
      pushdown(mid + 1, r, node << 1 | 1);
      tree[node].min = min(tree[node << 1].min, tree[node << 1 | 1].min);
    }
  if ((l != r) && (tree[node].ord)) {
    int mid = (l + r) >> 1;
    tree[node << 1] = tree[node << 1 | 1] = tree[node];
    tree[node].ord = 0;
  }
  return;
}
inline long long asktree(int l, int r, int x, int node) {
  pushdown(l, r, node);
  if (tree[node].ord == 1) return tree[node].sum - tree[node].min;
  int mid = (l + r) >> 1;
  if (x <= mid)
    return asktree(l, mid, x, node << 1);
  else
    return asktree(mid + 1, r, x, node << 1 | 1);
}
inline void resettree(int l, int r, int x, int y, int z, int node) {
  pushdown(l, r, node);
  if ((l == x) && (r == y))
    tree[node] = resetnode(z);
  else {
    int mid = (l + r) >> 1;
    if (y <= mid)
      resettree(l, mid, x, y, z, node << 1);
    else if (x > mid)
      resettree(mid + 1, r, x, y, z, node << 1 | 1);
    else {
      resettree(l, mid, x, mid, z, node << 1);
      resettree(mid + 1, r, mid + 1, y, z, node << 1 | 1);
    }
    pushdown(l, mid, node << 1);
    pushdown(mid + 1, r, node << 1 | 1);
    tree[node].min = min(tree[node << 1].min, tree[node << 1 | 1].min);
  }
  return;
}
inline void addtree(int l, int r, int x, int y, int z, int node) {
  pushdown(l, r, node);
  if ((l == x) && (r == y))
    tree[node].add = tree[node].add + z;
  else {
    int mid = (l + r) >> 1;
    if (y <= mid)
      addtree(l, mid, x, y, z, node << 1);
    else if (x > mid)
      addtree(mid + 1, r, x, y, z, node << 1 | 1);
    else {
      addtree(l, mid, x, mid, z, node << 1);
      addtree(mid + 1, r, mid + 1, y, z, node << 1 | 1);
    }
    pushdown(l, mid, node << 1);
    pushdown(mid + 1, r, node << 1 | 1);
    tree[node].min = min(tree[node << 1].min, tree[node << 1 | 1].min);
  }
  pushdown(l, r, node);
  return;
}
int main() {
  n = fastscanf(), m = fastscanf();
  buildtree(1, n, 1);
  for (i = 1; i <= m; i++) {
    t = fastscanf();
    if (t == 1) {
      z = fastscanf();
      printf("%I64d\n", asktree(1, n, z, 1));
    }
    if (t == 2) {
      x = fastscanf(), y = fastscanf(), z = fastscanf();
      resettree(1, n, x, y, z, 1);
    }
    if (t == 3) {
      x = fastscanf(), y = fastscanf(), z = fastscanf();
      addtree(1, n, x, y, z, 1);
      while (!tree[1].min) addtree(1, n, x, y, z, 1);
    }
  }
  return 0;
}
