#include <bits/stdc++.h>
using uint = unsigned int;
#define int uint
char buf[1 << 20], *p1, *p2;
#define gc() ((p1 == p2 && p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) ? EOF : *p1++)
inline int read() {
int res = 0;
char c = gc();
while (!isdigit(c)) c = gc();
while (isdigit(c)) res = (res << 1) + (res << 3) + (c ^ 48), c = gc();
return res;
}
constexpr int N = 200005, mod = 1 << 20;
template<class T>
inline int fmod(T x) {
return x & ((1 << 20) - 1);
}
int n, q;
int a[N];
int C[200005][25];
struct node {
int l, r;
uint v[22], t;
}tree[N << 2];
#define ls(p) (p << 1)
#define rs(p) (ls(p) | 1)
#define l(p) tree[p].l
#define r(p) tree[p].r
#define v(p) tree[p].v
#define t(p) tree[p].t
#define len(p) (r(p) - l(p) + 1)
inline void merge(int *c, int *a, int *b) {
for (int i = 0; i < 20; i++) {
c[i] = 0;
for (int j = 0; j <= i; j++)
c[i] = a[j] * b[i - j] + c[i];
}
}
inline void pushup(int p) {
merge(v(p), v(ls(p)), v(rs(p)));
}
void build(int p, int l, int r) {
// std::cout << p << ' ' << l << ' ' << r << '\n';
l(p) = l, r(p) = r, t(p) = 0;
if (l == r) {
memset(v(p), 0, sizeof(v(p)));
v(p)[0] = 1;
v(p)[1] = a[l] - 1;
return;
}
int mid = (l + r) >> 1;
build(ls(p), l, mid);
build(rs(p), mid + 1, r);
pushup(p);
}
inline void node_add(int p, uint x) {
// std::cout << "ADD: " << p << ' ' << x << '\n';
t(p) = fmod(t(p) + x);
static uint pow[22];
pow[0] = 1;
for (int i = 1; i < 20; i++) pow[i] = pow[i - 1] * x;
for (int i = 19; i >= 0; i--) {
for (int j = i - 1; j >= 0; j--) {
v(p)[i] = v(p)[j] * pow[i - j] * C[len(p) - j][i - j] + v(p)[i];
}
}
}
inline void pushdown(int p) {
if (!t(p)) return;
// std::cout << "pushdown "<< p << ' ' << t(p) << '\n';
node_add(ls(p), t(p));
node_add(rs(p), t(p));
t(p) = 0;
}
void add(int p, int l, int r, int x) {
if (l > r(p) || r < l(p)) return;
if (l <= l(p) && r(p) <= r) {
node_add(p, x);
return;
}
pushdown(p);
add(ls(p), l, r, x);
add(rs(p), l, r, x);
pushup(p);
}
int ans[22];
void qry(int p, int l, int r) {
if (l > r(p) || r < l(p)) return;
if (l <= l(p) && r(p) <= r) {
// std::cout << p << '\n';
static int rans[22];
memcpy(rans, ans, sizeof ans);
merge(ans, rans, v(p));
return;
}
pushdown(p);
qry(ls(p), l, r);
qry(rs(p), l, r);
}
inline int Qry(int l, int r) {
memset(ans, 0, sizeof ans);
ans[0] = 1;
qry(1, l, r);
uint res = 0;
for (int i = 0; i < 20; i++) res += ans[i];
return fmod(res);
}
signed main() {
std::cin.tie(0)->sync_with_stdio(0);
for (int i = 0; i <= 200000; i++) {
C[i][0] = 1;
for (int j = 1; j <= 20; j++)
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
n = read(), q = read();
for (int i = 1; i <= n; i++) a[i] = read();
build(1, 1, n);
int op, l, r, x;
while (q--) {
op = read(), l = read(), r = read();
if (op == 1) {
x = read();
add(1, l, r, x);
} else {
std::cout << Qry(l, r << '\n';
// for (int i = 0; i < 20; i++) std::cout << v(11)[i] << ' ';
}
}
}