#include using namespace std; #define MAXM 24 #define MAXN (1 << MAXM) typedef long long LL; typedef LL lint; const int p = 998244353; template T Add(T x, int p) { return x >= p ? x - p : x; } inline int ls(int rt) { return rt << 1; } inline int rs(int rt) { return rt << 1 | 1; } char op[MAXN]; struct SGT { lint s[MAXN]; void Init(int n) { Build(1, 1, n); } inline lint merge(int rt, lint v1, lint v2) { if (op[rt] == 0) { return Add(v1 + v2, p); } else { return (LL)v1 * v2 % p; } } void PushUp(int rt) { s[rt] = merge(rt, s[ls(rt)], s[rs(rt)]); } void Build(int rt, int l, int r) { if (l == r) { s[rt] = r; } else { int mid = (l + r) >> 1; Build(ls(rt), l, mid); Build(rs(rt), mid+1, r); PushUp(rt); } } void Modify(int rt, int l, int r, int x, int v) { if (l == r) { s[rt] = v; } else { int mid = (l + r) >> 1; if (x <= mid) { Modify(ls(rt), l, mid, x, v); } else { Modify(rs(rt), mid+1, r, x, v); } PushUp(rt); } } lint Query(int rt, int l, int r, int x) { if (l == r) { return 1; } else { int mid = (l + r) >> 1; lint ans, to; if (x <= mid) { ans = s[rs(rt)]; to = Query(ls(rt), l, mid, x); } else { ans = s[ls(rt)]; to = Query(rs(rt), mid+1, r, x); } if (op[rt] == 0) { return to; } else { return (LL)ans * to % p; } } } }; int main() { int m, q; static SGT sgt; scanf("%d%d", &m, &q); int n = (1 << (m-1)); scanf("%s", op + 1); for (int i = 1; i < n; ++i) { op[i] -= '0'; } sgt.Init(n); while (q--) { int o, i; scanf("%d%d", &o, &i); if (o == 1) { int y; scanf("%d", &y); sgt.Modify(1, 1, n, i, y); } else { printf("%d\n", (int)sgt.Query(1, 1, n, i)); } } return 0; }