#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define mp make_pair
#define pb push_back

#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#define rep(i, n) for (int i = 0; i < (int)(n); ++ i)

// Data Structure

template <int mxn> struct UF {
	int fa[mxn], rk[mxn];
	UF() { rep(i, mxn) fa[i] = i, rk[i] = 1; }
	int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
	void merge(int x, int y) {
		x = find(x); y = find(y);
		if (x == y) return ;
		if (rk[x] < rk[y]) fa[x] = y;
		else fa[y] = x, rk[x] += rk[x] == rk[y];
	}
};

template <typename T, int mxn> struct BIT {
	T s[mxn + 5];
	void upd(int x, T v) { for (++ x; x < mxn + 5; x += x & -x) s[x] = s[x] + v; }
	T qry(int x) { T ans = T(); for (++ x; x; x -= x & -x) ans = ans + s[x]; return ans; }
	T qry(int l, int r) { if (l >= r) return T(); return qry(r - 1) - qry(l - 1); }
};

template <typename T, int mxn> struct BITR {
	T s0[mxn + 5], s1[mxn + 5];
	void upd(int x, T v) { int ox = x; for (++ x; x < mxn + 5; x += x & -x) s0[x] = s0[x] + v, s1[x] = s1[x] + 1LL * ox * v; }
	T qry(int x) { T ans = T(); int ox = x; for (++ x; x; x -= x & -x) ans = ans + (s0[x] * (ox + 1) - s1[x]); return ans; }
	void upd(int l, int r, T v) { if (l >= r) return ; upd(l, v); upd(r, -v); }
	void qry(int l, int r) { if (l >= r) return T(); return qry(r - 1) - qry(l - 1); }
};

template <typename T, int mxn> struct SEG {
	T va[mxn << 1];
	void pushup(int x) {
		va[x] = va[x << 1] + va[x << 1 | 1];
	}
	void init(T *a, int n) {
		rep(i, n) va[i + mxn] = a[i];
		for (int i = mxn - 1; i; -- i) pushup(i);
	}
	void set(int x, T v) {
		va[x += mxn] = v;
		while (x >>= 1) pushup(x);
	}
	T get(int x) {
		return va[x + mxn];
	}
	T qry(int l, int r) {
		if (l >= r) return T();
		T L = T(), R = T();
		for (l += mxn, r += mxn; l < r; l >>= 1, r >>= 1) {
			if (l & 1) L = L + va[l ++];
			if (r & 1) R = va[-- r] + R;
		}
		return L + R;
	}
};

template <typename T0, typename T1, int mxn> struct SEGR {
	T0 va[mxn << 1]; T1 tag[mxn << 1]; int k;
	SEGR() { k = __builtin_ctz(mxn); }
	void push(int x, T1 v) {
		va[x] = va[x] + v;
		tag[x] = tag[x] + v;
	}
	void pushdown(int x) {
		push(x << 1, tag[x]);
		push(x << 1 | 1, tag[x]);
		tag[x] = T1();
	}
	void pushup(int x) {
		va[x] = va[x << 1] + va[x << 1 | 1];
	}
	void init(T0 *a, int n) {
		rep(i, n) va[i + mxn] = a[i];
		for (int i = mxn - 1; i; -- i) pushup(i);
	}
	void set(int x, T0 v) {
		x += mxn;
		for (int i = k; i; -- i) pushdown(x >> i);
		va[x] = v;
		while (x >>= 1) pushup(x);
	}
	T0 get(int x) {
		x += mxn;
		for (int i = k; i; -- i) pushdown(x >> i);
		return va[x];
	}
	void upd(int l, int r, T1 v) {
		if (l >= r) return ;
		l += mxn, r += mxn;
		for (int i = k; i >= 1; -- i) {
			if (((l >> i) << i) != l) pushdown(l >> i);
			if (((r >> i) << i) != r) pushdown(r >> i);
		}
		int l0 = l, r0 = r;
		for (; l < r; l >>= 1, r >>= 1) {
			if (l & 1) push(l ++, v);
			if (r & 1) push(-- r, v);
		}
		for (int i = 1; i <= k; ++ i) {
			if (((l0 >> i) << i) != l0) pushup(l0 >> i);
			if (((r0 >> i) << i) != r0) pushup(r0 >> i);
		}
	}
	T0 qry(int l, int r) {
		if (l >= r) return T0();
		l += mxn, r += mxn;
		for (int i = k; i >= 1; -- i) {
			if (((l >> i) << i) != l) pushdown(l >> i);
			if (((r >> i) << i) != r) pushdown(r >> i);
		}
		T0 L = T0(), R = T0();
		for (; l < r; l >>= 1, r >>= 1) {
			if (l & 1) L = L + va[l ++];
			if (r & 1) R = va[-- r] + R;
		}
		return L + R;
	}
};

// Number Theory

int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }

int exgcd(int a, int b, int &x, int &y) {
	if (b == 0) { x = 1; y = 0; return a; }
	else { int d = exgcd(b, a % b, y, x); y -= a / b * x; return d; }
}

template <int mod> struct rem {
	int v;
	rem(int v = 0, bool fl = 0) { if (fl) { v %= mod; if (v < 0) v += mod; } this->v = v; }
	friend rem operator += (rem &a, const rem &b) { a.v += b.v; if (a.v >= mod) a.v -= mod; return a; }
	friend rem operator -= (rem &a, const rem &b) { a.v -= b.v; if (a.v < 0) a.v += mod; return a; }
	friend rem operator *= (rem &a, const rem &b) { a.v = 1LL * a.v * b.v % mod; return a; }
	friend rem operator /= (rem &a, const rem &b) { a.v = 1LL * a.v * inv(b).v % mod; return a; }
	friend rem qp(rem x, int n) { rem ans = 1; for (; n; n >>= 1, x *= x) if (n & 1) ans *= x; return ans; }
	friend rem inv(rem v) { int x, y; exgcd(v, mod, x, y); return rem(x, 1); }
	friend rem operator + (rem a, const rem &b) { return a += b; }
	friend rem operator - (rem a, const rem &b) { return a -= b; }
	friend rem operator * (rem a, const rem &b) { return a *= b; }
	friend rem operator / (rem a, const rem &b) { return a /= b; }
	friend rem operator - (const rem &a) { return rem(mod - a.v); }
	operator int () { return v; }
};

const int mod = 998244353;
typedef rem <mod> mint;

// Fast IO

#define FASTIO

namespace IO {
#ifdef FASTIO
	const int msz = 1 << 22;
	char ibuf[msz], *ied = ibuf + msz, *ips = ied, obuf[msz], *oed = obuf + msz, *ops = obuf;
	inline char GC() { if (ips == ied) ied = ibuf + fread(ips = ibuf, 1, msz, stdin); return *ips ++; }
	inline void PC(char c) { if (ops == oed) fwrite(ops = obuf, 1, msz, stdout); *ops ++ = c; }
	struct FLUSHER { ~FLUSHER() { fwrite(obuf, 1, ops - obuf, stdout); } } flusher;
#else
	inline char GC() { return getchar_unlocked(); }
	inline void PC(char c) { putchar_unlocked(c); }
#endif
};

template <typename T> inline void read(T &x) {
	x = 0; int f = 1, c = IO::GC();
	while (c <= 32) c = IO::GC();
	if (c == 45) f = 0, c = IO::GC();
	while (c > 32) x = x * 10 + c - 48, c = IO::GC();
	x = f ? x : -x;
}
template <int mod> inline void read(rem <mod> &x) { int v; read(v); x = rem <mod> (v, 1); }
inline void read(char &x) { x = IO::GC(); while (isspace(x)) x = IO::GC(); }
inline void read(char *s) {
	while (isspace(*s = IO::GC())) ;
	while (!isspace(*++ s = IO::GC())) ;
	*s = 0;
}

template <typename T> inline void write(T x) {
	static char buf[25];
	char *top = buf;
	if (x < 0) IO::PC(45), x = -x;
	if (x == 0) IO::PC(48);
	while (x) *top ++ = x % 10 + 48, x /= 10;
	do IO::PC(*-- top); while (top != buf);
}
template <int mod> inline void write(rem <mod> x) { write(x.v); }
inline void write(char x) { IO::PC(x); }
inline void write(const char *s) { while (*s) IO::PC(*s ++); }
template <typename T> inline void writeln(T x) { write(x); write('\n'); }

// template end

struct T1 {
	mint a, b;
	T1(mint a = 1, mint b = 0): a(a), b(b) {}
	T1 operator + (const T1 &rhs) const { return T1(a * rhs.a, b * rhs.a + rhs.b); }
};

struct T0 {
	mint v;
	int sz;
	T0(mint v = 0, int sz = 0): v(v), sz(sz) {}
	T0 operator + (const T0 &rhs) const { return T0(v + rhs.v, sz + rhs.sz); }
	T0 operator + (const T1 &rhs) const { return T0(v * rhs.a + sz * rhs.b, sz); }
};

const int mxn = 1 << 19;
int n, q;
T0 a[mxn];
SEGR <T0, T1, mxn> seg;

int main() {
	read(n); read(q);
	rep(i, n) read(a[i].v), a[i].sz = 1;
	seg.init(a, n);
	while (q --) {
		int tp; read(tp);
		if (tp == 0) {
			int l, r, a, b;
			read(l); read(r); read(a); read(b);
			seg.upd(l, r, T1(a, b));
		}
		else if (tp == 1) {
			int l, r;
			read(l); read(r);
			writeln(seg.qry(l, r).v);
		}
	}
	return 0;
}


Measured memory_bytes: 30640